@wendongfly/myhi 1.3.208 → 1.3.209
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat.html +7 -6
- package/dist/chat.html.gz +0 -0
- package/dist/index.html +40 -2
- package/dist/index.html.gz +0 -0
- package/dist/index.js +6 -6
- package/dist/index.min.js +5 -5
- package/package.json +1 -1
package/dist/index.min.js
CHANGED
|
@@ -373,12 +373,12 @@ Content-Length: `+C+`\r
|
|
|
373
373
|
`,{mode:384})}catch{}}function loadAudit(d,i=500){if(!d)return[];try{return(0,external_fs_.readFileSync)(auditPath(d),"utf8").trim().split(`
|
|
374
374
|
`).filter(Boolean).slice(-i).map((t=>{try{return JSON.parse(t)}catch{return null}})).filter(Boolean)}catch{return[]}}function buildPseudonymizer(d,i){const n=getProjectGuard(d),t=i&&i.byVal?i:newMap();if(!n.enabled)return{enabled:!1,level:n.level,map:t,size:Object.keys(t.byVal).length,pseudonymize:o=>({text:o,count:0}),restore:o=>o};const e=LEVELS[n.level]||LEVELS[DEFAULT_LEVEL],s={};for(const[o,c]of Object.entries(t.byVal))s[c.ph]=o;function u(o,c){if(t.byVal[o])return t.byVal[o].ph;t.counters[c]=(t.counters[c]||0)+1;const r=`\u3010${c}_${t.counters[c]}\u3011`;return t.byVal[o]={ph:r,type:c},s[r]=o,r}function f(o){if(typeof o!="string"||!o||o.length>2e5)return{text:o,count:0};const c=[];e.pii&&c.push(...PII);const r=e.dict?n.entities:[];e.amount&&c.push(...AMOUNT);for(const v of c){const g=o.match(v.re);if(g)for(const _ of g)t.byVal[_]||u(_,v.type)}for(const v of r)v.name&&o.includes(v.name)&&!t.byVal[v.name]&&u(v.name,v.type||"\u4E3B\u4F53");const a=Object.keys(t.byVal).filter((v=>o.includes(v)));a.sort(((v,g)=>g.length-v.length));let h=o,m=0;const p={};for(const v of a)if(h.includes(v)){const g=t.byVal[v].type;h=h.split(v).join(t.byVal[v].ph),m++,p[g]=(p[g]||0)+1}return{text:h,count:m,byType:p}}function l(o){return typeof o!="string"||!o||o.indexOf("\u3010")<0?o:o.replace(PLACEHOLDER_RE,(c=>s[c]!==void 0?s[c]:c))}return{enabled:!0,level:n.level,map:t,size:Object.keys(t.byVal).length,pseudonymize:f,restore:l}}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 d=JSON.parse((0,external_fs_.readFileSync)(INBOX_FILE,"utf8"));return Array.isArray(d)?d:[]}catch{return[]}}function saveDrafts(d){try{(0,external_fs_.mkdirSync)(CONFIG_DIR,{recursive:!0});const i=INBOX_FILE+".tmp";return(0,external_fs_.writeFileSync)(i,JSON.stringify(d,null,2),{mode:384}),(0,external_fs_.renameSync)(i,INBOX_FILE),!0}catch(i){return console.error("[inbox] \u5199\u5165\u5931\u8D25:",i.message),!1}}function projectNameOf(d){if(!d)return"";const i=String(d).replace(/\\/g,"/").split("/").filter(Boolean);return i[i.length-1]||""}function normAttach(d){return Array.isArray(d)?d.filter((i=>i&&typeof i.path=="string"&&i.path)).slice(0,10).map((i=>({path:i.path,name:i.name||i.path.split("/").pop()}))):[]}function listDrafts({sessionId:d,owner:i,includeAll:n=!0}={}){let t=loadDrafts();return d&&(t=t.filter((e=>e.sessionId===d))),i&&!n&&(t=t.filter((e=>!e.owner||e.owner===i))),t.sort(byOrder)}const orderOf=d=>typeof d.order=="number"?d.order:d.createdAt||0,byOrder=(d,i)=>orderOf(d)-orderOf(i)||(d.createdAt||0)-(i.createdAt||0);function reorderDrafts(d,i=[]){const n=loadDrafts(),t=i.map((s=>n.find((u=>u.id===s&&u.sessionId===d)))).filter(Boolean);if(t.length<2)return!1;const e=t.map(orderOf).sort(((s,u)=>s-u));for(let s=1;s<e.length;s++)e[s]<=e[s-1]&&(e[s]=e[s-1]+1);return t.forEach(((s,u)=>{s.order=e[u],s.updatedAt=Date.now()})),saveDrafts(n),!0}function mergeDrafts(d=[]){const i=loadDrafts(),n=i.filter((o=>d.includes(o.id))).sort(byOrder);if(n.length<2)throw new Error("\u81F3\u5C11\u9009\u4E24\u6761\u8349\u7A3F\u624D\u80FD\u5408\u5E76");const t=n[0].sessionId;if(n.some((o=>o.sessionId!==t)))throw new Error("\u53EA\u80FD\u5408\u5E76\u540C\u4E00\u4E2A\u4EFB\u52A1\u7684\u8349\u7A3F");const e=n.map((o=>(o.text||"").trim())).filter(Boolean),s=e.length>1?e.map(((o,c)=>`${c+1}. ${o}`)).join(`
|
|
375
375
|
|
|
376
|
-
`):e[0]||"",u=n[0],f={...u,id:(0,external_crypto_.randomUUID)(),clientKey:null,text:s.slice(0,MAX_TEXT),images:normAttach(n.flatMap((o=>o.images||[]))),files:normAttach(n.flatMap((o=>o.files||[]))),autoSend:n.some((o=>o.autoSend)),source:"merged",order:orderOf(u),mergedFrom:n.flatMap((o=>o.mergedFrom?.length?o.mergedFrom:[{...o,mergedFrom:void 0}])).slice(0,50),createdAt:Math.min(...n.map((o=>o.createdAt||Date.now()))),updatedAt:Date.now()},l=i.filter((o=>!d.includes(o.id)));return l.push(f),saveDrafts(l),f}function unmergeDraft(d){const i=loadDrafts(),n=i.find((s=>s.id===d));if(!n||!n.mergedFrom?.length)throw new Error("\u8FD9\u6761\u4E0D\u662F\u5408\u5E76\u51FA\u6765\u7684\u8349\u7A3F");const t=n.mergedFrom.map((s=>({...s,sessionId:n.sessionId,claudeSessionId:n.claudeSessionId,sessionTitle:n.sessionTitle,cwd:n.cwd,projectName:n.projectName,updatedAt:Date.now()}))),e=i.filter((s=>s.id!==d)).concat(t);return saveDrafts(e),t}function countBySession(){const d={};for(const i of loadDrafts())i.sessionId&&(d[i.sessionId]=(d[i.sessionId]||0)+1);return d}function addDraft(d={},i=null){const n=String(d.text||"").slice(0,MAX_TEXT),t=normAttach(d.images),e=normAttach(d.files);if(!n.trim()&&!t.length&&!e.length)throw new Error("\u8349\u7A3F\u5185\u5BB9\u4E3A\u7A7A");if(!d.sessionId)throw new Error("\u8349\u7A3F\u5FC5\u987B\u5F52\u5C5E\u4E00\u4E2A\u4F1A\u8BDD");const s=typeof d.clientKey=="string"&&d.clientKey?d.clientKey.slice(0,64):null;if(s){const o=loadDrafts().find((c=>c.clientKey===s));if(o)return o}const u=i?.cwd||d.cwd||"",f={id:(0,external_crypto_.randomUUID)(),clientKey:s,text:n,images:t,files:e,sessionId:d.sessionId,claudeSessionId:i?.claudeSessionId||d.claudeSessionId||null,sessionTitle:i?.title||d.sessionTitle||"(\u672A\u77E5\u4EFB\u52A1)",cwd:u,projectName:projectNameOf(u),owner:d.owner||i?.owner||null,autoSend:!!d.autoSend,source:d.source||"manual",order:Date.now(),createdAt:Date.now(),updatedAt:Date.now()},l=loadDrafts();for(l.push(f);l.length>MAX_DRAFTS;)l.shift();return saveDrafts(l),f}function updateDraft(d,i={},n=null){const t=loadDrafts(),e=t.findIndex((u=>u.id===d));if(e<0)return null;const s=t[e];return typeof i.text=="string"&&(s.text=i.text.slice(0,MAX_TEXT)),typeof i.autoSend=="boolean"&&(s.autoSend=i.autoSend),i.images&&(s.images=normAttach(i.images)),i.files&&(s.files=normAttach(i.files)),i.sessionId&&i.sessionId!==s.sessionId&&(s.sessionId=i.sessionId,s.claudeSessionId=n?.claudeSessionId||null,s.sessionTitle=n?.title||i.sessionTitle||s.sessionTitle,s.cwd=n?.cwd||i.cwd||s.cwd,s.projectName=projectNameOf(s.cwd),s.order=Date.now()),s.updatedAt=Date.now(),t[e]=s,saveDrafts(t),s}function removeDraft(d){const i=loadDrafts(),n=i.filter((t=>t.id!==d));return n.length===i.length?!1:(saveDrafts(n),!0)}function rebindDrafts(d=[]){const i=new Map;for(const s of d)s.claudeSessionId&&i.set(s.claudeSessionId,s);const n=new Set(d.map((s=>s.id))),t=loadDrafts();let e=0;for(const s of t){if(n.has(s.sessionId)||!s.claudeSessionId)continue;const u=i.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(t),e}function syncSessionTitle(d,i){const n=loadDrafts();let t=!1;for(const e of n)e.sessionId===d&&e.sessionTitle!==i&&(e.sessionTitle=i,t=!0);t&&saveDrafts(n)}function buildDraftPrompt(d){const i=(d.text||"").trim(),n=d.images?.[0],t=d.files?.[0];if((d.images?.length||0)+(d.files?.length||0)>1){const e=[];return d.images?.length&&e.push(`\u7528\u6237\u4E0A\u4F20\u4E86 ${d.images.length} \u5F20\u56FE\u7247\uFF0C\u8DEF\u5F84\u5206\u522B\u662F ${d.images.map((s=>s.path)).join("\u3001")}\uFF0C\u8BF7\u7528 Read \u5DE5\u5177\u9010\u4E00\u8BFB\u53D6\u3002`),d.files?.length&&e.push(`\u7528\u6237\u4E0A\u4F20\u4E86 ${d.files.length} \u4E2A\u4E34\u65F6\u6587\u4EF6\u7528\u4E8E\u672C\u6B21\u5206\u6790\uFF08\u4E0D\u5728\u9879\u76EE\u6587\u4EF6\u6811\u91CC\uFF09\uFF1A${d.files.map((s=>`${s.path}\uFF08\u539F\u6587\u4EF6\u540D ${s.name}\uFF09`)).join("\u3001")}\uFF0C\u8BF7\u7528\u5408\u9002\u7684\u5DE5\u5177\u8BFB\u53D6\u3002`),e.join("")+`\u7528\u6237\u7684\u8981\u6C42\u662F\uFF1A${i||"\u5206\u6790\u8FD9\u4E9B\u5185\u5BB9"}`}return n?`\u7528\u6237\u4E0A\u4F20\u4E86\u4E00\u5F20\u56FE\u7247\uFF0C\u8DEF\u5F84\u662F ${n.path}\uFF0C\u8BF7\u7528 Read \u5DE5\u5177\u8BFB\u53D6\u8FD9\u5F20\u56FE\u7247\u3002\u7528\u6237\u7684\u8981\u6C42\u662F\uFF1A${i||"\u63CF\u8FF0\u56FE\u7247\u5185\u5BB9"}`:t?`\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 ${t.path}\uFF08\u539F\u6587\u4EF6\u540D ${t.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${i||"\u5206\u6790\u8FD9\u4E2A\u6587\u4EF6"}`:i}function nextAutoSendDraft(d){return d&&loadDrafts().filter((n=>n.sessionId===d&&n.autoSend)).sort(byOrder)[0]||null}function draftDisplayText(d){const i=(d.text||"").trim(),n=d.images?.[0],t=d.files?.[0];return(d.images?.length||0)+(d.files?.length||0)>1?`${[d.images?.length?`\u{1F4F7}\xD7${d.images.length}`:"",d.files?.length?`\u{1F4CE}\xD7${d.files.length}`:""].filter(Boolean).join(" ")} ${i}`.trim():n?`\u{1F4F7} ${i||"\u5206\u6790\u56FE\u7247"}`:t?`\u{1F4CE} ${t.name}${i?" "+i:""}`:i}const SCENES={main:"\u4E3B\u4EFB\u52A1",plan:"\u8BA1\u5212",subagent:"\u5B50\u4EE3\u7406",background:"\u540E\u53F0\u5C0F\u4EFB\u52A1",ask:"\u95EE\u4E00\u95EE / \u89E3\u91CA",voice:"\u8BED\u97F3\u6574\u7406",vision:"\u770B\u56FE"},myhiDir=()=>(0,external_path_.join)((0,external_os_.homedir)(),".myhi");function readJson(d){try{return JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(myhiDir(),d),"utf8").replace(/^/,""))||{}}catch{return{}}}function sceneFit(d,i){if(!i)return"";if(d==="main"||d==="plan"||d==="subagent"){if(i.caps?.length&&!i.caps.includes("function_calling"))return"\u4E0D\u652F\u6301\u5DE5\u5177\u8C03\u7528\uFF0CAI \u6CA1\u6CD5\u8BFB\u5199\u6587\u4EF6\u3001\u8DD1\u547D\u4EE4";if(i.protocols&&!i.protocols.includes("anthropic"))return"\u4E0D\u8D70 Anthropic \u63A5\u53E3\uFF0CClaude Code \u7528\u4E0D\u4E86\u5B83\u7684\u5DE5\u5177"}return d==="vision"&&i.caps?.length&&!i.caps.includes("vision")?"\u4E0D\u80FD\u770B\u56FE":""}function hasGateway(){const d=readJson("gateway.json");return!!(d.baseUrl&&d.apiKey)}function readSceneModels(){const d=readJson("config.json");if(!hasGateway())return Object.fromEntries(Object.keys(SCENES).map((t=>[t,""])));const i=d.models&&typeof d.models=="object"?d.models:{},n={};for(const t of Object.keys(SCENES))n[t]=typeof i[t]=="string"?i[t].trim():"";return!n.ask&&typeof d.askModel=="string"&&(n.ask=d.askModel.trim()),n}const sceneModel=d=>readSceneModels()[d]||"";let _cache=null;const TTL=10*6e4;async function listGatewayModels({force:d=!1}={}){const i=readJson("gateway.json");if(!i.baseUrl||!i.apiKey)return{gateway:!1,scoped:!1,models:[]};const n=i.baseUrl+"|"+i.apiKey.slice(-6);if(!d&&_cache&&_cache.key===n&&Date.now()-_cache.at<TTL)return annotateTime(_cache.value);let t;try{const e=await fetch(i.baseUrl.replace(/\/+$/,"")+"/v1/models?scope=token",{headers:{"x-api-key":i.apiKey,Authorization:"Bearer "+i.apiKey,"anthropic-version":"2023-06-01"},signal:AbortSignal.timeout(8e3)});if(!e.ok)throw new Error("\u7F51\u5173\u8FD4\u56DE HTTP "+e.status);const s=await e.json(),u=(Array.isArray(s.data)?s.data:[]).filter((c=>c&&c.id)).map((c=>({id:String(c.id),name:String(c.display_name||c.id),provider:String(c.provider||""),kind:c.kind==="alias"?"alias":"model",target:c.target?String(c.target):"",caps:Array.isArray(c.capabilities)?c.capabilities.map(String):[],tags:Array.isArray(c.tags)?c.tags.map(String):[],inputCost:typeof c.input_cost=="number"?c.input_cost:null,outputCost:typeof c.output_cost=="number"?c.output_cost:null,multiplier:typeof c.price_multiplier=="number"?c.price_multiplier:null,protocols:Array.isArray(c.protocols)?c.protocols.map(String):null})));for(const c of u)c.fit=Object.fromEntries(["main","plan","subagent","vision"].map((r=>[r,sceneFit(r,c)])));(Array.isArray(s.data)?s.data:[]).forEach(((c,r)=>{u[r]&&Array.isArray(c.time_pricing)&&(u[r].timeRules=c.time_pricing)}));const f=s.token&&typeof s.token=="object"?s.token:null,l=c=>typeof c=="number"?c:null,o=f?{name:f.name?String(f.name):"",dailyLimit:l(f.daily_credit_limit),dailyUsed:l(f.daily_credits_used),monthlyLimit:l(f.monthly_credit_limit),monthlyUsed:l(f.monthly_credits_used),expiresAt:f.expires_at?String(f.expires_at):null}:null;t={gateway:!0,scoped:s.scope==="token",models:u,token:o,periods:s.time_periods||null}}catch(e){t={gateway:!0,scoped:!1,models:[],error:e.message}}return _cache={at:t.error?Date.now()-TTL+6e4:Date.now(),key:n,value:t},annotateTime(t)}const WD={Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6,Sun:7};function nowIn(d){try{const i=Object.fromEntries(new Intl.DateTimeFormat("en-US",{timeZone:d||"Asia/Shanghai",hour:"2-digit",minute:"2-digit",weekday:"short",hourCycle:"h23"}).formatToParts(new Date).map((n=>[n.type,n.value])));return{hm:`${i.hour}:${i.minute}`,wd:WD[i.weekday]||0}}catch{return null}}function inWindow(d,i){const n=nowIn(i);if(!n||!d?.start)return!1;const t=d.start,e=d.end||d.start,s=Array.isArray(d.days)&&d.days.length?d.days:null,u=f=>!s||s.includes(f);return t===e?u(n.wd):t<e?n.hm>=t&&n.hm<e&&u(n.wd):n.hm>=t&&u(n.wd)||n.hm<e&&u(n.wd===1?7:n.wd-1)}function annotateTime(d){if(!d?.models)return d;const i=d.periods||{},n=d.models.map((t=>{if(!t.timeRules?.length)return t;for(const e of t.timeRules){const s=e.period?i[e.period==="offpeak"?"offpeak":"peak"]||[]:[e],u=e.period?i.timezone:e.timezone;if(s.some((f=>inWindow(f,u)))){const f=e.label||(e.period==="offpeak"?"\u95F2\u65F6":e.period==="peak"?"\u5FD9\u65F6":"\u65F6\u6BB5\u4EF7");return{...t,timeNow:{label:f,multiplier:typeof e.multiplier=="number"?e.multiplier:null}}}}return t}));return{...d,models:n}}const wildRe=d=>new RegExp("^"+d.split("*").map((i=>i.replace(/[.+?^${}()|[\]\\]/g,"\\$&"))).join(".*")+"$","i");async function modelSeesImages(d){const{models:i=[]}=await listGatewayModels();if(!i.length)return null;const n=d?[d]:["opus","claude-opus-5-5"],t=e=>i.find((s=>s.id===e))||i.find((s=>s.id.includes("*")&&wildRe(s.id).test(e)));for(const e of n){let s=t(e);if(s&&!s.caps?.length&&s.kind==="alias"&&s.target&&(s=t(s.target)||s),s?.caps?.length)return s.caps.includes("vision")}return null}const MIME={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp"},MAX_IMG=5*1024*1024,_descCache=new Map,VISION_PROMPT=d=>`\u4F60\u662F\u770B\u56FE\u52A9\u624B\uFF1A\u53E6\u4E00\u4E2A\u770B\u4E0D\u5230\u56FE\u7247\u7684 AI \u8981\u9760\u4F60\u7684\u6587\u5B57\u6765\u7406\u89E3\u8FD9\u5F20\u56FE\uFF0C\u8BF7\u7528\u4E2D\u6587\u5BA2\u89C2\u3001\u5B8C\u6574\u5730\u63CF\u8FF0\u5B83\u3002
|
|
376
|
+
`):e[0]||"",u=n[0],f={...u,id:(0,external_crypto_.randomUUID)(),clientKey:null,text:s.slice(0,MAX_TEXT),images:normAttach(n.flatMap((o=>o.images||[]))),files:normAttach(n.flatMap((o=>o.files||[]))),autoSend:n.some((o=>o.autoSend)),source:"merged",order:orderOf(u),mergedFrom:n.flatMap((o=>o.mergedFrom?.length?o.mergedFrom:[{...o,mergedFrom:void 0}])).slice(0,50),createdAt:Math.min(...n.map((o=>o.createdAt||Date.now()))),updatedAt:Date.now()},l=i.filter((o=>!d.includes(o.id)));return l.push(f),saveDrafts(l),f}function unmergeDraft(d){const i=loadDrafts(),n=i.find((s=>s.id===d));if(!n||!n.mergedFrom?.length)throw new Error("\u8FD9\u6761\u4E0D\u662F\u5408\u5E76\u51FA\u6765\u7684\u8349\u7A3F");const t=n.mergedFrom.map((s=>({...s,sessionId:n.sessionId,claudeSessionId:n.claudeSessionId,sessionTitle:n.sessionTitle,cwd:n.cwd,projectName:n.projectName,updatedAt:Date.now()}))),e=i.filter((s=>s.id!==d)).concat(t);return saveDrafts(e),t}function countBySession(){const d={};for(const i of loadDrafts())i.sessionId&&(d[i.sessionId]=(d[i.sessionId]||0)+1);return d}function addDraft(d={},i=null){const n=String(d.text||"").slice(0,MAX_TEXT),t=normAttach(d.images),e=normAttach(d.files);if(!n.trim()&&!t.length&&!e.length)throw new Error("\u8349\u7A3F\u5185\u5BB9\u4E3A\u7A7A");if(!d.sessionId)throw new Error("\u8349\u7A3F\u5FC5\u987B\u5F52\u5C5E\u4E00\u4E2A\u4F1A\u8BDD");const s=typeof d.clientKey=="string"&&d.clientKey?d.clientKey.slice(0,64):null;if(s){const o=loadDrafts().find((c=>c.clientKey===s));if(o)return o}const u=i?.cwd||d.cwd||"",f={id:(0,external_crypto_.randomUUID)(),clientKey:s,text:n,images:t,files:e,sessionId:d.sessionId,claudeSessionId:i?.claudeSessionId||d.claudeSessionId||null,sessionTitle:i?.title||d.sessionTitle||"(\u672A\u77E5\u4EFB\u52A1)",cwd:u,projectName:projectNameOf(u),owner:d.owner||i?.owner||null,autoSend:!!d.autoSend,source:d.source||"manual",order:Date.now(),createdAt:Date.now(),updatedAt:Date.now()},l=loadDrafts();for(l.push(f);l.length>MAX_DRAFTS;)l.shift();return saveDrafts(l),f}function updateDraft(d,i={},n=null){const t=loadDrafts(),e=t.findIndex((u=>u.id===d));if(e<0)return null;const s=t[e];return typeof i.text=="string"&&(s.text=i.text.slice(0,MAX_TEXT)),typeof i.autoSend=="boolean"&&(s.autoSend=i.autoSend),i.images&&(s.images=normAttach(i.images)),i.files&&(s.files=normAttach(i.files)),i.sessionId&&i.sessionId!==s.sessionId&&(s.sessionId=i.sessionId,s.claudeSessionId=n?.claudeSessionId||null,s.sessionTitle=n?.title||i.sessionTitle||s.sessionTitle,s.cwd=n?.cwd||i.cwd||s.cwd,s.projectName=projectNameOf(s.cwd),s.order=Date.now()),s.updatedAt=Date.now(),t[e]=s,saveDrafts(t),s}function removeDraft(d){const i=loadDrafts(),n=i.filter((t=>t.id!==d));return n.length===i.length?!1:(saveDrafts(n),!0)}function rebindDrafts(d=[]){const i=new Map;for(const s of d)s.claudeSessionId&&i.set(s.claudeSessionId,s);const n=new Set(d.map((s=>s.id))),t=loadDrafts();let e=0;for(const s of t){if(n.has(s.sessionId)||!s.claudeSessionId)continue;const u=i.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(t),e}function syncSessionTitle(d,i){const n=loadDrafts();let t=!1;for(const e of n)e.sessionId===d&&e.sessionTitle!==i&&(e.sessionTitle=i,t=!0);t&&saveDrafts(n)}function buildDraftPrompt(d){const i=(d.text||"").trim(),n=d.images?.[0],t=d.files?.[0];if((d.images?.length||0)+(d.files?.length||0)>1){const e=[];return d.images?.length&&e.push(`\u7528\u6237\u4E0A\u4F20\u4E86 ${d.images.length} \u5F20\u56FE\u7247\uFF0C\u8DEF\u5F84\u5206\u522B\u662F ${d.images.map((s=>s.path)).join("\u3001")}\uFF0C\u8BF7\u7528 Read \u5DE5\u5177\u9010\u4E00\u8BFB\u53D6\u3002`),d.files?.length&&e.push(`\u7528\u6237\u4E0A\u4F20\u4E86 ${d.files.length} \u4E2A\u4E34\u65F6\u6587\u4EF6\u7528\u4E8E\u672C\u6B21\u5206\u6790\uFF08\u4E0D\u5728\u9879\u76EE\u6587\u4EF6\u6811\u91CC\uFF09\uFF1A${d.files.map((s=>`${s.path}\uFF08\u539F\u6587\u4EF6\u540D ${s.name}\uFF09`)).join("\u3001")}\uFF0C\u8BF7\u7528\u5408\u9002\u7684\u5DE5\u5177\u8BFB\u53D6\u3002`),e.join("")+`\u7528\u6237\u7684\u8981\u6C42\u662F\uFF1A${i||"\u5206\u6790\u8FD9\u4E9B\u5185\u5BB9"}`}return n?`\u7528\u6237\u4E0A\u4F20\u4E86\u4E00\u5F20\u56FE\u7247\uFF0C\u8DEF\u5F84\u662F ${n.path}\uFF0C\u8BF7\u7528 Read \u5DE5\u5177\u8BFB\u53D6\u8FD9\u5F20\u56FE\u7247\u3002\u7528\u6237\u7684\u8981\u6C42\u662F\uFF1A${i||"\u63CF\u8FF0\u56FE\u7247\u5185\u5BB9"}`:t?`\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 ${t.path}\uFF08\u539F\u6587\u4EF6\u540D ${t.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${i||"\u5206\u6790\u8FD9\u4E2A\u6587\u4EF6"}`:i}function nextAutoSendDraft(d){return d&&loadDrafts().filter((n=>n.sessionId===d&&n.autoSend)).sort(byOrder)[0]||null}function draftDisplayText(d){const i=(d.text||"").trim(),n=d.images?.[0],t=d.files?.[0];return(d.images?.length||0)+(d.files?.length||0)>1?`${[d.images?.length?`\u{1F4F7}\xD7${d.images.length}`:"",d.files?.length?`\u{1F4CE}\xD7${d.files.length}`:""].filter(Boolean).join(" ")} ${i}`.trim():n?`\u{1F4F7} ${i||"\u5206\u6790\u56FE\u7247"}`:t?`\u{1F4CE} ${t.name}${i?" "+i:""}`:i}const SCENES={main:"\u4E3B\u4EFB\u52A1",plan:"\u8BA1\u5212",subagent:"\u5B50\u4EE3\u7406",background:"\u540E\u53F0\u5C0F\u4EFB\u52A1",ask:"\u95EE\u4E00\u95EE / \u89E3\u91CA",voice:"\u8BED\u97F3\u6574\u7406",vision:"\u770B\u56FE"},myhiDir=()=>(0,external_path_.join)((0,external_os_.homedir)(),".myhi");function readJson(d){try{return JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(myhiDir(),d),"utf8").replace(/^/,""))||{}}catch{return{}}}function sceneFit(d,i){if(!i)return"";if(d==="main"||d==="plan"||d==="subagent"){if(i.caps?.length&&!i.caps.includes("function_calling"))return"\u4E0D\u652F\u6301\u5DE5\u5177\u8C03\u7528\uFF0CAI \u6CA1\u6CD5\u8BFB\u5199\u6587\u4EF6\u3001\u8DD1\u547D\u4EE4";if(i.protocols&&!i.protocols.includes("anthropic"))return"\u4E0D\u8D70 Anthropic \u63A5\u53E3\uFF0CClaude Code \u7528\u4E0D\u4E86\u5B83\u7684\u5DE5\u5177"}return d==="vision"&&i.caps?.length&&!i.caps.includes("vision")?"\u4E0D\u80FD\u770B\u56FE":""}function hasGateway(){return!!resolveGateway().baseUrl}function resolveGateway(){const d=s=>/^https?:\/\/([^/]*\.)?anthropic\.com(\/|$)/i.test(s),i=(s,u,f)=>s&&u&&!d(s)?{baseUrl:String(s).trim(),apiKey:String(u).trim(),source:f}:null,n=readJson("gateway.json"),t=process.env;let e={};try{e=JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(t.CLAUDE_CONFIG_DIR||(0,external_path_.join)((0,external_os_.homedir)(),".claude"),"settings.json"),"utf8").replace(/^\uFEFF/,"")).env||{}}catch{}return i(n.baseUrl,n.apiKey,"myhi")||i(t.ANTHROPIC_BASE_URL,t.ANTHROPIC_API_KEY||t.ANTHROPIC_AUTH_TOKEN,"env")||i(e.ANTHROPIC_BASE_URL,e.ANTHROPIC_API_KEY||e.ANTHROPIC_AUTH_TOKEN,"claude")||{baseUrl:"",apiKey:"",source:null}}function readSceneModels(){const d=readJson("config.json");if(!hasGateway())return Object.fromEntries(Object.keys(SCENES).map((t=>[t,""])));const i=d.models&&typeof d.models=="object"?d.models:{},n={};for(const t of Object.keys(SCENES))n[t]=typeof i[t]=="string"?i[t].trim():"";return!n.ask&&typeof d.askModel=="string"&&(n.ask=d.askModel.trim()),n}const sceneModel=d=>readSceneModels()[d]||"";let _cache=null;const TTL=10*6e4;async function listGatewayModels({force:d=!1}={}){const i=resolveGateway();if(!i.baseUrl||!i.apiKey)return{gateway:!1,scoped:!1,models:[]};const n=i.baseUrl+"|"+i.apiKey.slice(-6);if(!d&&_cache&&_cache.key===n&&Date.now()-_cache.at<TTL)return annotateTime(_cache.value);let t;try{const e=await fetch(i.baseUrl.replace(/\/+$/,"")+"/v1/models?scope=token",{headers:{"x-api-key":i.apiKey,Authorization:"Bearer "+i.apiKey,"anthropic-version":"2023-06-01"},signal:AbortSignal.timeout(8e3)});if(!e.ok)throw new Error("\u7F51\u5173\u8FD4\u56DE HTTP "+e.status);const s=await e.json(),u=(Array.isArray(s.data)?s.data:[]).filter((c=>c&&c.id)).map((c=>({id:String(c.id),name:String(c.display_name||c.id),provider:String(c.provider||""),kind:c.kind==="alias"?"alias":"model",target:c.target?String(c.target):"",caps:Array.isArray(c.capabilities)?c.capabilities.map(String):[],tags:Array.isArray(c.tags)?c.tags.map(String):[],inputCost:typeof c.input_cost=="number"?c.input_cost:null,outputCost:typeof c.output_cost=="number"?c.output_cost:null,multiplier:typeof c.price_multiplier=="number"?c.price_multiplier:null,protocols:Array.isArray(c.protocols)?c.protocols.map(String):null})));for(const c of u)c.fit=Object.fromEntries(["main","plan","subagent","vision"].map((r=>[r,sceneFit(r,c)])));(Array.isArray(s.data)?s.data:[]).forEach(((c,r)=>{u[r]&&Array.isArray(c.time_pricing)&&(u[r].timeRules=c.time_pricing)}));const f=s.token&&typeof s.token=="object"?s.token:null,l=c=>typeof c=="number"?c:null,o=f?{name:f.name?String(f.name):"",dailyLimit:l(f.daily_credit_limit),dailyUsed:l(f.daily_credits_used),monthlyLimit:l(f.monthly_credit_limit),monthlyUsed:l(f.monthly_credits_used),expiresAt:f.expires_at?String(f.expires_at):null}:null;t={gateway:!0,scoped:s.scope==="token",models:u,token:o,periods:s.time_periods||null}}catch(e){t={gateway:!0,scoped:!1,models:[],error:e.message}}return _cache={at:t.error?Date.now()-TTL+6e4:Date.now(),key:n,value:t},annotateTime(t)}const WD={Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6,Sun:7};function nowIn(d){try{const i=Object.fromEntries(new Intl.DateTimeFormat("en-US",{timeZone:d||"Asia/Shanghai",hour:"2-digit",minute:"2-digit",weekday:"short",hourCycle:"h23"}).formatToParts(new Date).map((n=>[n.type,n.value])));return{hm:`${i.hour}:${i.minute}`,wd:WD[i.weekday]||0}}catch{return null}}function inWindow(d,i){const n=nowIn(i);if(!n||!d?.start)return!1;const t=d.start,e=d.end||d.start,s=Array.isArray(d.days)&&d.days.length?d.days:null,u=f=>!s||s.includes(f);return t===e?u(n.wd):t<e?n.hm>=t&&n.hm<e&&u(n.wd):n.hm>=t&&u(n.wd)||n.hm<e&&u(n.wd===1?7:n.wd-1)}function annotateTime(d){if(!d?.models)return d;const i=d.periods||{},n=d.models.map((t=>{if(!t.timeRules?.length)return t;for(const e of t.timeRules){const s=e.period?i[e.period==="offpeak"?"offpeak":"peak"]||[]:[e],u=e.period?i.timezone:e.timezone;if(s.some((f=>inWindow(f,u)))){const f=e.label||(e.period==="offpeak"?"\u95F2\u65F6":e.period==="peak"?"\u5FD9\u65F6":"\u65F6\u6BB5\u4EF7");return{...t,timeNow:{label:f,multiplier:typeof e.multiplier=="number"?e.multiplier:null}}}}return t}));return{...d,models:n}}const wildRe=d=>new RegExp("^"+d.split("*").map((i=>i.replace(/[.+?^${}()|[\]\\]/g,"\\$&"))).join(".*")+"$","i");async function modelSeesImages(d){const{models:i=[]}=await listGatewayModels();if(!i.length)return null;const n=d?[d]:["opus","claude-opus-5-5"],t=e=>i.find((s=>s.id===e))||i.find((s=>s.id.includes("*")&&wildRe(s.id).test(e)));for(const e of n){let s=t(e);if(s&&!s.caps?.length&&s.kind==="alias"&&s.target&&(s=t(s.target)||s),s?.caps?.length)return s.caps.includes("vision")}return null}const MIME={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp"},MAX_IMG=5*1024*1024,_descCache=new Map,VISION_PROMPT=d=>`\u4F60\u662F\u770B\u56FE\u52A9\u624B\uFF1A\u53E6\u4E00\u4E2A\u770B\u4E0D\u5230\u56FE\u7247\u7684 AI \u8981\u9760\u4F60\u7684\u6587\u5B57\u6765\u7406\u89E3\u8FD9\u5F20\u56FE\uFF0C\u8BF7\u7528\u4E2D\u6587\u5BA2\u89C2\u3001\u5B8C\u6574\u5730\u63CF\u8FF0\u5B83\u3002
|
|
377
377
|
- \u56FE\u91CC\u6240\u6709\u80FD\u770B\u6E05\u7684\u6587\u5B57\u539F\u6837\u8F6C\u5199\uFF08\u4FDD\u6301\u6362\u884C\uFF1B\u8868\u683C\u7528 Markdown \u8868\u683C\uFF1B\u4EE3\u7801 / \u62A5\u9519\u539F\u6587\u653E\u4EE3\u7801\u5757\uFF09
|
|
378
378
|
- \u622A\u56FE\uFF1A\u8BF4\u660E\u662F\u4EC0\u4E48\u754C\u9762\u3001\u5E03\u5C40\u3001\u5173\u952E\u6309\u94AE / \u63D0\u793A / \u72B6\u6001\uFF1B\u7167\u7247 / \u56FE\u8868\uFF1A\u8BF4\u660E\u4E3B\u4F53\u3001\u6570\u636E\u3001\u8D8B\u52BF
|
|
379
379
|
- \u770B\u4E0D\u6E05\u6216\u4E0D\u786E\u5B9A\u7684\u5730\u65B9\u660E\u786E\u6807\u51FA\uFF0C\u4E0D\u8981\u731C
|
|
380
380
|
- \u53EA\u63CF\u8FF0\uFF0C\u4E0D\u8981\u56DE\u7B54\u6216\u6267\u884C\u7528\u6237\u7684\u8981\u6C42
|
|
381
|
-
`+(d?`\u7528\u6237\u5BF9\u8FD9\u5F20\u56FE\u7684\u8981\u6C42\u662F\uFF1A\u300C${d}\u300D\u2014\u2014\u548C\u5B83\u76F8\u5173\u7684\u7EC6\u8282\u63CF\u8FF0\u5F97\u66F4\u4ED4\u7EC6\u3002`:"");async function describeImage(d,{model:i,question:n="",signal:t}={}){const e=
|
|
381
|
+
`+(d?`\u7528\u6237\u5BF9\u8FD9\u5F20\u56FE\u7684\u8981\u6C42\u662F\uFF1A\u300C${d}\u300D\u2014\u2014\u548C\u5B83\u76F8\u5173\u7684\u7EC6\u8282\u63CF\u8FF0\u5F97\u66F4\u4ED4\u7EC6\u3002`:"");async function describeImage(d,{model:i,question:n="",signal:t}={}){const e=resolveGateway();if(!e.baseUrl||!e.apiKey)throw new Error("\u6CA1\u914D\u7F51\u5173");const s=MIME[(0,external_path_.extname)(d).toLowerCase()];if(!s)throw new Error("\u4E0D\u652F\u6301\u7684\u56FE\u7247\u683C\u5F0F");if((0,external_fs_.statSync)(d).size>MAX_IMG)throw new Error("\u56FE\u7247\u8D85\u8FC7 5MB");const u=(0,external_fs_.readFileSync)(d),f=(0,external_crypto_.createHash)("sha1").update(u).update("\0"+i+"\0"+n).digest("hex");if(_descCache.has(f))return _descCache.get(f);const l=await fetch(e.baseUrl.replace(/\/+$/,"")+"/v1/messages",{method:"POST",headers:{"content-type":"application/json","x-api-key":e.apiKey,Authorization:"Bearer "+e.apiKey,"anthropic-version":"2023-06-01"},body:JSON.stringify({model:i,max_tokens:2048,messages:[{role:"user",content:[{type:"image",source:{type:"base64",media_type:s,data:u.toString("base64")}},{type:"text",text:VISION_PROMPT(n)}]}]}),signal:t?AbortSignal.any([t,AbortSignal.timeout(9e4)]):AbortSignal.timeout(9e4)}),o=await l.json().catch((()=>({})));if(!l.ok)throw new Error(o?.error?.message||"\u7F51\u5173\u8FD4\u56DE HTTP "+l.status);const c=(o.content||[]).filter((r=>r.type==="text")).map((r=>r.text)).join(`
|
|
382
382
|
`).trim();if(!c)throw new Error("\u770B\u56FE\u6A21\u578B\u6CA1\u6709\u8FD4\u56DE\u5185\u5BB9");return _descCache.set(f,c),_descCache.size>100&&_descCache.delete(_descCache.keys().next().value),c}let _launcher=null;function resolveWinLauncherFromCmd(d){try{const i=(0,external_fs_.readFileSync)(d,"utf8"),n=(0,external_path_.dirname)(d),t=s=>s.trim().replace(/%~?dp0%?/gi,n+"\\").replace(/\\{2,}/g,"\\");let e=i.match(/"?([^"\r\n]*claude\.exe)"?/i);if(e){const s=t(e[1]);if((0,external_fs_.existsSync)(s))return{command:s,preArgs:[]}}if(e=i.match(/"?([^"\r\n]*\.js)"?\s+%\*/i),e){const s=t(e[1]);if((0,external_fs_.existsSync)(s))return{command:process.execPath,preArgs:[s]}}}catch{}return null}function winLauncherFromPath(d){if(/\.exe$/i.test(d))return{command:d,preArgs:[]};if(/\.cmd$/i.test(d)){const i=resolveWinLauncherFromCmd(d);return i||{command:process.env.ComSpec||"cmd.exe",preArgs:["/c",d]}}return{command:d,preArgs:[]}}function findClaude(){if(_launcher)return _launcher;const d=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")],i=t=>process.platform==="win32"?winLauncherFromPath(t):{command:t,preArgs:[]},n=t=>console.log(`[agent] ${t} claude:`,_launcher.command,..._launcher.preArgs.length?[_launcher.preArgs[_launcher.preArgs.length-1]]:[]);for(const t of d)if((0,external_fs_.existsSync)(t))return _launcher=i(t),n("\u627E\u5230"),_launcher;try{const t=process.platform==="win32"?"where claude.cmd":"which claude",e=(0,external_child_process_namespaceObject.execSync)(t,{timeout:5e3,stdio:"pipe"}).toString().trim().split(`
|
|
383
383
|
`)[0].trim();if(e)return _launcher=i(e),n("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,_interactiveCap=null,_replayCap=!1}let _interactiveCap=null,_replayCap=!1;function probeInteractive(){return _interactiveCap!==null?Promise.resolve(_interactiveCap):new Promise((d=>{let i;try{i=findClaude()}catch{return _interactiveCap=!1,d(!1)}let n="",t=!1;const e=f=>{t||(t=!0,_interactiveCap=f&&!process.env.MYHI_NO_INTERACTIVE,_replayCap=/--replay-user-messages/.test(n)&&!process.env.MYHI_NO_INJECT,d(_interactiveCap))};let s;try{s=(0,external_child_process_namespaceObject.spawn)(i.command,[...i.preArgs,"--help"],{stdio:["ignore","pipe","pipe"]})}catch{return e(!1)}const u=setTimeout((()=>{try{s.kill()}catch{}e(!1)}),1e4);s.stdout.on("data",(f=>{n+=f.toString()})),s.on("error",(()=>{clearTimeout(u),e(!1)})),s.on("close",(()=>{clearTimeout(u),e(/--permission-prompt-tool/.test(n)&&/--allow-dangerously-skip-permissions/.test(n))}))}))}function getClaudeVersion(){return new Promise((d=>{let i;try{i=findClaude()}catch{return d(null)}let n="",t=!1;const e=f=>{t||(t=!0,d(f))};let s;try{s=(0,external_child_process_namespaceObject.spawn)(i.command,[...i.preArgs,"--version"],{stdio:["ignore","pipe","pipe"]})}catch{return e(null)}const u=setTimeout((()=>{try{s.kill()}catch{}e(null)}),1e4);s.stdout.on("data",(f=>{n+=f.toString()})),s.on("error",(()=>{clearTimeout(u),e(null)})),s.on("close",(()=>{clearTimeout(u);const f=n.match(/(\d+\.\d+\.\d+)/);e(f?{version:f[1],raw:n.trim()}:null)}))}))}const BASE64_STRIP_THRESHOLD=5*1024;function stripHeavyPayload(d){if(d==null||typeof d!="object")return d;if(Array.isArray(d))return d.map(stripHeavyPayload);const i={};for(const[n,t]of Object.entries(d))typeof t=="string"&&t.length>BASE64_STRIP_THRESHOLD&&(n==="data"||n==="url"&&t.startsWith("data:"))?i[n]=`[STRIPPED_BASE64_${t.length}_CHARS]`:i[n]=stripHeavyPayload(t);return i}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,INTERACTION_WAIT_MS=Number(process.env.MYHI_ASK_WAIT_MS)||1800*1e3,INTERACTION_WAIT_FOLLOW_MS=Number(process.env.MYHI_ASK_WAIT_FOLLOW_MS)||180*1e3,INJECT_FOLLOW_WAIT_MS=Number(process.env.MYHI_INJECT_WAIT_MS)||2e4,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","","{{MODE}}","","\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(`
|
|
384
384
|
`),EXEC_MODE_PROMPT=["\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\u6587\u4EF6\u7F16\u8F91\u6388\u6743\u3001\u5BA1\u6279\u6309\u94AE\u8FD9\u7C7B\u4EA4\u4E92\u3002","\u4F60\u60F3\u597D\u65B9\u6848\u5C31\u76F4\u63A5\u7528\u5DE5\u5177\u6267\u884C\uFF0C\u7EDD\u4E0D\u8981\u8BF4\u300C\u7B49\u5F85\u6279\u51C6\u300D\u300C\u8BF7\u70B9\u51FB\u786E\u8BA4\u6309\u94AE\u300D\u300C\u9700\u8981\u4F60\u6388\u6743\u300D\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"].join(`
|
|
@@ -389,7 +389,7 @@ Content-Length: `+C+`\r
|
|
|
389
389
|
\uFF08\u6CE8\u610F\uFF1A\u4F60\u5F53\u524D\u7528\u7684\u6A21\u578B\u4E0D\u80FD\u76F4\u63A5\u770B\u56FE\uFF0C\u4E0D\u8981\u7528 Read \u8BFB\u53D6\u4E0A\u9762\u7684\u56FE\u7247\u6587\u4EF6\u3002myhi \u5DF2\u7528\u770B\u56FE\u6A21\u578B ${u} \u628A\u56FE\u7247\u8F6C\u6210\u4E86\u4E0B\u9762\u7684\u6587\u5B57\u3002\u63CF\u8FF0\u91CC\u6CA1\u6709\u7684\u7EC6\u8282\u8BF7\u5982\u5B9E\u8BF4\u770B\u4E0D\u5230\uFF0C\u5FC5\u8981\u65F6\u5EFA\u8BAE\u7528\u6237\u6362\u80FD\u770B\u56FE\u7684\u6A21\u578B\u518D\u95EE\u3002\uFF09`+r.map((p=>`
|
|
390
390
|
|
|
391
391
|
\u3010\u56FE\u7247 ${p.path}\u3011
|
|
392
|
-
${p.text||"\uFF08\u8BC6\u522B\u5931\u8D25\uFF1A"+p.error+"\uFF09"}`)).join(""):i}_modelPlan(){
|
|
392
|
+
${p.text||"\uFF08\u8BC6\u522B\u5931\u8D25\uFF1A"+p.error+"\uFF09"}`)).join(""):i}_modelPlan(){const i=this.modelId||sceneModel("main"),n=sceneModel("plan");if(n&&n!==i){if(i&&!/^(opus|sonnet|haiku|fable|best|default|opusplan)(\[1m\])?$/i.test(i))return{model:"opusplan",opus:n,sonnet:i};if(this.permissionMode==="plan")return{model:n}}return{model:i}}_currentModel(){const i=this._modelPlan();return i.model==="opusplan"?this.permissionMode==="plan"?i.opus:i.sonnet:i.model||null}_buildArgs(){const i=["--output-format","stream-json","--input-format","stream-json","--verbose"],n=normalizePermissionMode(this.permissionMode),t=_interactiveCap===!0;this._interactive=t,this._injectable=_replayCap,_replayCap&&i.push("--replay-user-messages");const e=n==="plan"?planModePrompt(t):EXEC_MODE_PROMPT+(t?`
|
|
393
393
|
`+ASK_PROMPT:""),s=MYHI_SYSTEM_PROMPT.replace("{{MODE}}",e)+(process.platform==="win32"?`
|
|
394
394
|
`+MYHI_WIN_ENCODING_PROMPT:"");if(i.push("--append-system-prompt",s.replace(/\s*\n\s*/g," ").trim()),t&&(i.push("--permission-prompt-tool","stdio"),i.push("--disallowedTools","EnterPlanMode"),n!=="plan"&&i.push("--disallowedTools","ExitPlanMode"),n==="plan"&&i.push("--allow-dangerously-skip-permissions")),n==="bypassPermissions")i.push("--dangerously-skip-permissions");else if(n==="plan")i.push("--permission-mode","plan"),i.push("--allowedTools","WebSearch"),i.push("--allowedTools","WebFetch");else if(n==="acceptEdits"){i.push("--permission-mode","acceptEdits");const f=["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 l of f)i.push("--allowedTools",l)}const{model:u}=this._modelPlan();return u&&i.push("--model",u),this.claudeSessionId&&i.push("--resume",this.claudeSessionId),i}_writeStdin(i){if(!this._proc||!this._proc.stdin?.writable)return!1;try{return this._proc.stdin.write(JSON.stringify(i)+`
|
|
395
395
|
`),!0}catch{return!1}}_spawnProcess(){this._expectExit=!1,this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null);const i=findClaude(),n=this._buildArgs(),t=this._buildEnv();this._usageBase=JSON.parse(JSON.stringify(this._usage)),this._procQueryCount=0;const e=i.command,s=[...i.preArgs,...n];console.log(`[agent] \u542F\u52A8\u6301\u4E45\u8FDB\u7A0B: ${e} ${i.preArgs.join(" ")} (\u4F1A\u8BDD: ${this.claudeSessionId||"\u65B0\u5EFA"})`),this._proc=(0,external_child_process_namespaceObject.spawn)(e,s,{cwd:this.cwd,env:t,stdio:["pipe","pipe","pipe"]});const u=this._proc,f=()=>this._proc!==null&&this._proc!==u;this._buffer="",this._proc.stdout.on("data",(o=>{if(f())return;this._buffer+=o.toString();const c=this._buffer.split(`
|
|
@@ -397,7 +397,7 @@ ${p.text||"\uFF08\u8BC6\u522B\u5931\u8D25\uFF1A"+p.error+"\uFF09"}`)).join(""):i
|
|
|
397
397
|
`).map((h=>h.trim())).filter(Boolean),a=r.filter((h=>!l.some((m=>m.test(h)))));r.length>a.length&&console.log(`[agent:stderr][benign] \u541E\u6389 ${r.length-a.length} \u6761\u826F\u6027\u63D0\u793A`),a.length&&(console.error("[agent:stderr]",a.join(`
|
|
398
398
|
`)),this.emit("agent:error",{message:a.join(`
|
|
399
399
|
`)}),this._checkDeathLoop({type:"stderr",_raw:a.join(`
|
|
400
|
-
`)}))})),this._proc.on("close",(o=>{if(f()){console.log(`[agent] \u65E7\u8FDB\u7A0B\u9000\u51FA (code ${o})\uFF0C\u5DF2\u88AB\u65B0\u8FDB\u7A0B\u66FF\u6362\uFF0C\u5FFD\u7565`);return}if(!this._interrupted&&this._buffer.trim())try{const c=JSON.parse(this._buffer.trim());this._handleMessage(c)}catch{}if(this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._stopStallWatchdog(),this._proc=null,this._buffer="",this._dropInteractions(),this._dropInjected("Claude \u8FDB\u7A0B\u5DF2\u9000\u51FA\uFF0C\u8FD9\u6761\u63D2\u8BDD\u6CA1\u6709\u9001\u8FBE"),console.log(`[agent] \u8FDB\u7A0B\u9000\u51FA (code ${o}), \u4F1A\u8BDD: ${this.claudeSessionId||"?"}`),this._busy&&(this._busy=!1,this._interrupted=!1,this.emit("agent:busy",!1),this._pendingReject&&(this._pendingReject(new Error(`Claude \u8FDB\u7A0B\u9000\u51FA (code ${o})`)),this._pendingResolve=null,this._pendingReject=null)),this._flushPendingSteer(),this._spawnFailed){this._spawnFailed=!1;return}if(this._expectExit){this._expectExit=!1;return}this.alive&&o!==0&&o!==null&&this.emit("agent:error",{message:`Claude \u8FDB\u7A0B\u5F02\u5E38\u9000\u51FA (code ${o})\uFF0C\u4E0B\u6B21\u67E5\u8BE2\u5C06\u81EA\u52A8\u91CD\u542F`})})),this._proc.on("error",(o=>{f()||(this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._stopStallWatchdog(),this._proc=null,this._busy=!1,this.emit("agent:busy",!1),this._spawnFailed=!0,this.emit("agent:error",{message:o.code==="ENOENT"?CLAUDE_MISSING_MSG:`\u542F\u52A8 Claude \u5931\u8D25: ${o.message}`}),o.reported=!0,this._pendingReject&&(this._pendingReject(o),this._pendingResolve=null,this._pendingReject=null))})),this._keepAliveTimer=setInterval((()=>{this._writeStdin({type:"keep_alive"})}),3e4)}async query(i,{internal:n=!1,from:t=null,display:e=null,actor:s=null}={}){if(this._busy){this.emit("agent:error",{message:"\u6B63\u5728\u5904\u7406\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u5B8C\u6210"});return}if(n||(this._followCount=0,this._followStopSignal=!1,this._cancelFollowUp()),i==="/clear"){this.reset();const o=[CLEAR_WHERE[s?.where],s?.device].filter(Boolean).join(" \xB7 "),c=s?.via==="button"?"\u70B9\u4E86\u300C\u6E05\u9664\u300D":"\u53D1\u9001\u4E86 /clear",r=s?`${s.name||"\u7528\u6237"}${o?`\uFF08${o}\uFF09`:""}${c}\uFF0C`:"";console.log(`[clear] \u4F1A\u8BDD ${this.id}\u300C${this.title||""}\u300D\u88AB\u6E05\u9664\uFF1A${s?`${s.name||"?"} / ${CLEAR_WHERE[s.where]||"\u672A\u77E5\u9875\u9762"} / ${s.device||"?"} / ${s.via}`:"\u5185\u90E8\u8C03\u7528"}`),this.emit("agent:message",{type:"system",subtype:"info",cleared:!0,message:`${r}\u5DF2\u5F00\u59CB\u65B0\u5BF9\u8BDD\uFF1AAI \u4E0D\u518D\u8BB0\u5F97\u4E4B\u524D\u804A\u8FC7\u7684\u5185\u5BB9\uFF08\u9879\u76EE\u6587\u4EF6\u4E0D\u53D7\u5F71\u54CD\uFF09`});return}const u=i.match(/^\/resume\s+(\S+)/);if(u){if(this._proc){this._expectExit=!0;try{this._proc.kill("SIGTERM")}catch{}this._proc=null}this.claudeSessionId=u[1],this._history=[],this._buffer="",this._loadResumedHistory(),this.emit("agent:message",{type:"system",subtype:"info",message:`\u5DF2\u5207\u6362\u5230\u4F1A\u8BDD ${u[1].slice(0,8)}...\uFF0C\u4E0B\u6B21\u63D0\u95EE\u5C06\u6062\u590D\u8BE5\u5BF9\u8BDD`});return}const f=i.match(/^\/model\s+(\S+)/);if(f&&!hasGateway()){this.emit("agent:message",{type:"system",subtype:"info",message:"\u6CA1\u6709\u914D\u7F6E\u81EA\u5B9A\u4E49\u7F51\u5173\uFF1A\u4F7F\u7528 Claude Code \u9ED8\u8BA4\u6A21\u578B\uFF0C\u4E0D\u63D0\u4F9B\u6A21\u578B\u5207\u6362\u3002\u914D\u7F6E\u7F51\u5173\u540E\u53EF\u5728\u804A\u5929\u6846\u7684\u6A21\u578B\u6309\u94AE\u91CC\u9009"});return}if(f){if(this.modelId=f[1]==="default"?null:f[1],this.emit("settings-changed"),this._proc){this._expectExit=!0;try{this._proc.kill("SIGTERM")}catch{}this._proc=null}const o=this.modelId||sceneModel("main");this.emit("agent:message",{type:"system",subtype:"info",message:this.modelId?`\u6A21\u578B\u5DF2\u5207\u6362\u4E3A ${this.modelId}`:`\u5DF2\u6062\u590D\u9ED8\u8BA4\u6A21\u578B${o?`\uFF08${o}\uFF09`:"\uFF08Claude Code \u9ED8\u8BA4\uFF09"}`});return}if(i==="/plan"||i.startsWith("/plan ")){if(this.permissionMode==="plan"){if(this.permissionMode=normalizePermissionMode(this._prePlanMode),this._prePlanMode=null,this._proc){this._expectExit=!0;try{this._proc.kill("SIGTERM")}catch{}this._proc=null}this.emit("agent:message",{type:"system",subtype:"info",message:"\u5DF2\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"})}else{if(this._prePlanMode=this.permissionMode,this.permissionMode="plan",this._proc){this._expectExit=!0;try{this._proc.kill("SIGTERM")}catch{}this._proc=null}this.emit("agent:message",{type:"system",subtype:"info",message:"\u5DF2\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F\uFF08\u53EA\u89C4\u5212\u4E0D\u6267\u884C\uFF09"});const c=i.slice(5).trim();if(c){setTimeout((()=>this.query(c)),500);return}}return}if(i.startsWith("/rename")){this.emit("agent:message",{type:"system",subtype:"info",message:"\u4F1A\u8BDD\u5DF2\u547D\u540D"});return}this._busy=!0,this._interrupted=!1,this.emit("agent:busy",!0),this._loopSigCounts.clear(),this._loopPoisonHits=0,this._loopTurnToolCalls=0,this._loopTripped=!1,n||(this._loopAutoRecover=0),this._redactor=buildRedactor(),this._pseudoMap||(this._pseudoMap=loadMap(this.claudeSessionId||this.id)),this._pseudo=buildPseudonymizer(this.cwd,this._pseudoMap),this._lastActivityAt=Date.now(),this._awaitingTool=!1,this._startStallWatchdog();const l=redactDeep(typeof e=="string"&&e.trim()?e.trim().slice(0,500):i,this._redactor);this._history.push({type:"user",content:l,timestamp:Date.now()}),t&&this.emit("agent:message",{type:"user",content:l,timestamp:Date.now(),from:t}),!this.firstUserText&&typeof l=="string"&&!l.startsWith("/")&&(this.firstUserText=l.trim().slice(0,160));try{i=await this._prepareImages(i)}catch(o){if(o.name==="AbortError"||this._describeAborted){this._describeAborted=!1,this._busy=!1,this._stopStallWatchdog(),this.emit("agent:busy",!1),this.emit("agent:message",{type:"system",subtype:"interrupted"});return}console.warn("[\u770B\u56FE] \u51FA\u9519\uFF0C\u6309\u539F\u6837\u53D1\u9001:",o.message)}return this._lastActivityAt=Date.now(),this._proc||(_interactiveCap===null&&await probeInteractive(),this._spawnProcess()),new Promise(((o,c)=>{this._pendingResolve=o,this._pendingReject=c,i.startsWith("/")&&(this._slashTimeout=setTimeout((()=>{this._busy&&(this._busy=!1,this._interrupted=!1,this.emit("agent:busy",!1),this.emit("agent:message",{type:"system",subtype:"info",message:`\u547D\u4EE4 ${i} \u5DF2\u53D1\u9001`}),this._pendingResolve&&(this._pendingResolve(0),this._pendingResolve=null,this._pendingReject=null))}),3e4));let r=i;if(this._pseudo?.enabled){const h=this._pseudo.pseudonymize(i);r=h.text;const m=this.claudeSessionId||this.id;saveMap(m,this._pseudoMap),h.count>0&&(appendAudit(m,{ts:Date.now(),level:this._pseudo.level,maskedCount:h.count,byType:h.byType,sentToModel:h.text}),this.emit("agent:message",{type:"system",subtype:"info",message:`\u{1F6E1} \u9690\u79C1\u62A4\u680F\uFF1A\u672C\u8F6E\u5DF2\u8131\u654F ${h.count} \u5904\u654F\u611F\u4FE1\u606F\uFF0C\u6A21\u578B\u53EA\u770B\u5230\u5360\u4F4D\u7B26\uFF08\u6620\u5C04\u8868\u7559\u672C\u673A\u3001\u53EF\u9006\u8FD8\u539F\uFF09\u3002`}))}this._writeStdin({type:"user",uuid:(0,external_crypto_.randomUUID)(),message:{role:"user",content:r}})||(this._busy=!1,this.emit("agent:busy",!1),this._pendingResolve=null,this._pendingReject=null,c(new Error("Claude \u8FDB\u7A0B\u4E0D\u53EF\u5199")))}))}_handleMessage(i){const n=!!this.claudeSessionId;if(this._lastActivityAt=Date.now(),i.type==="assistant"&&Array.isArray(i.message?.content)?(!this._busy&&!i.parent_tool_use_id&&(this._busy=!0,this._interrupted=!1,this.emit("agent:busy",!0),this._lastActivityAt=Date.now(),this._startStallWatchdog()),i.message.content.some((l=>l.type==="tool_use"))&&(this._awaitingTool=!0)):i.type==="user"&&(this._awaitingTool=!1),i.type==="control_request"){this._onControlRequest(i);return}if(i.type==="control_response")return;if(i.type==="user"&&i.isReplay){this._onReplay(i);return}if(i.type==="system"&&i.subtype==="status"&&i.permissionMode){const l=normalizePermissionMode(i.permissionMode);VALID_PERMISSION_MODES.has(i.permissionMode)&&l!==this.permissionMode&&(this.permissionMode=l,l!=="plan"&&(this._prePlanMode=null),this.emit("mode-changed",l));return}if(i.session_id&&!this.claudeSessionId&&(this.claudeSessionId=i.session_id),i.type==="system"&&i.subtype==="init"&&i.session_id&&(this.claudeSessionId=i.session_id),!n&&this.claudeSessionId&&this.emit("session-id",this.claudeSessionId),i.type==="system"&&i.subtype==="init"&&this.permissionMode==="bypassPermissions"&&i.permissionMode&&i.permissionMode!=="bypassPermissions"){const l=i.permissionMode;this.reset(),this.emit("agent:message",{type:"system",subtype:"warning",message:`\u26A0\uFE0F \u8FD9\u4E2A\u4F1A\u8BDD\u88AB --resume \u5E26\u56DE\u4E86\u300C${l}\u300D\u6A21\u5F0F\uFF08\u975E bypass\uFF0C\u4F1A\u62E6\u5199/\u5220\u4E14\u65E0\u6CD5\u8FD0\u884C\u65F6\u63D0\u6743\uFF0C\u70B9\u300C\u9000\u51FA\u8BA1\u5212\u300D\u4E5F\u9003\u4E0D\u6389\uFF09\u3002\u5DF2\u81EA\u52A8\u65AD\u5F00\u65E7\u4F1A\u8BDD\u94FE\u3001\u91CD\u5F00\u4E3A\u5E72\u51C0\u7684 bypass \u4F1A\u8BDD\u2014\u2014\u8BF7\u91CD\u53D1\u4F60\u521A\u624D\u7684\u6307\u4EE4\uFF0C\u8FD9\u6B21\u4F1A\u76F4\u63A5\u6267\u884C\u3002`});return}const t=this._pseudo?.enabled?redactDeep(i,this._pseudo.restore):i,e=redactDeep(t,this._redactor),s=stripHeavyPayload({...e,timestamp:Date.now()}),u=JSON.stringify(s);this._followEnabled&&u.includes("[\u8DDF\u8FDB\u5B8C\u6210]")&&(this._followStopSignal=!0),u.length>10240&&(s._truncated=!0),this._history.push(s);const f=500;if(this._history.length>f&&(this._history=this._history.slice(-f)),this._trackImagePressure(u),this._checkDeathLoop(i,u),i.type==="rate_limit_event"&&i.rate_limit_info&&(this._usage.rateLimitInfo=i.rate_limit_info),i.type==="result"){const l=this._usageBase;if(this._procQueryCount=(this._procQueryCount||0)+1,this._usage.queryCount=l.queryCount+this._procQueryCount,i.total_cost_usd&&(this._usage.totalCostUSD=l.totalCostUSD+i.total_cost_usd),i.usage&&(this._usage.totalInputTokens=l.totalInputTokens+(i.usage.input_tokens||0),this._usage.totalOutputTokens=l.totalOutputTokens+(i.usage.output_tokens||0),this._usage.totalCacheReadTokens=l.totalCacheReadTokens+(i.usage.cache_read_input_tokens||0),this._usage.totalCacheCreationTokens=l.totalCacheCreationTokens+(i.usage.cache_creation_input_tokens||0)),i.modelUsage)for(const[o,c]of Object.entries(i.modelUsage)){const r=l.modelUsage[o]||{inputTokens:0,outputTokens:0,costUSD:0};this._usage.modelUsage[o]={inputTokens:r.inputTokens+(c.inputTokens||0),outputTokens:r.outputTokens+(c.outputTokens||0),costUSD:r.costUSD+(c.costUSD||0)}}}{let l=i.type==="assistant"?i.message?.usage:null;if(i.type==="result"&&(l=this._readTranscriptCtx()||l),l){const o=(l.input_tokens||0)+(l.cache_read_input_tokens||0)+(l.cache_creation_input_tokens||0);(o>this._contextTokens||this._contextTokens>0&&o<this._contextTokens*.5)&&(this._contextTokens=o)}}if(i.type==="result"&&(e.ctxTokens=this._contextTokens),i.type==="result"&&this._injected?.size&&(e.injectPending=!0),this.emit("agent:message",e),i.type==="result"){this._slashTimeout&&(clearTimeout(this._slashTimeout),this._slashTimeout=null),this._stopStallWatchdog();const l=!this._interrupted&&!i.is_error;if(this._pendingResolve&&(this._pendingResolve(0),this._pendingResolve=null,this._pendingReject=null),this._lastResultAt=Date.now(),this._injected?.size){this._interrupted=!1,this._lastActivityAt=Date.now(),this._startStallWatchdog(),clearTimeout(this._injectWaitTimer),this._injectWaitTimer=setTimeout((()=>{!this._injected?.size||!this._busy||(this._dropInjected("AI \u6CA1\u6709\u63A5\u6536\u8FD9\u6761\u63D2\u8BDD\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001"),this._busy=!1,this.emit("agent:busy",!1))}),INJECT_FOLLOW_WAIT_MS);return}this._busy=!1,this._interrupted=!1,this.emit("agent:busy",!1),this._skillsDirty&&setTimeout((()=>{this._busy||this.refreshSkills()}),0),this._flushPendingSteer(),l&&this._maybeRelayDraft(),this._maybeScheduleFollowUp()}}_trackImagePressure(i){const n=(i.match(/"type":"image"/g)||[]).length;n&&(this._imageBlockCount+=n,this._imageBlockCount>=this._imageNudgeAt&&(this._imageNudgeAt+=IMAGE_NUDGE_STEP,this.emit("agent:message",{type:"system",subtype:"warning",message:`\u2139\uFE0F \u672C\u4F1A\u8BDD\u5DF2\u7D2F\u79EF\u7EA6 ${this._imageBlockCount} \u5F20\u56FE\u7247\u3002\u56FE\u7247\u8D8A\u591A\u8D8A\u5BB9\u6613\u89E6\u53D1 API \u56FE\u7247\u5904\u7406\u9519\u8BEF\u5E76\u62D6\u6162/\u6D88\u8017\u989D\u5EA6\uFF0C\u5EFA\u8BAE\u7528 /clear \u91CD\u5F00\u4E00\u4E2A\u5E72\u51C0\u4F1A\u8BDD\uFF0C\u6216\u51CF\u5C11\u540E\u7EED\u622A\u56FE\u3002`})))}_checkDeathLoop(i,n){if(this._loopTripped)return;let t=!1;try{const e=n||JSON.stringify(i);if(LOOP_POISON_PHRASES.some((s=>e.includes(s)))){const s=i.type==="assistant",u=e.includes('"type":"image"'),f=e.length<=POISON_MAX_NOTICE_LEN;t=!s&&(u||f)}}catch{}if(t&&(this._loopPoisonHits++,this._loopPoisonHits>=LOOP_MAX_POISON_HITS)){this._tripLoopBreaker("\u8BE5\u56FE\u7247/\u5185\u5BB9 API \u53CD\u590D\u65E0\u6CD5\u5904\u7406\u5E76\u5DF2\u88AB\u79FB\u9664\uFF0C\u8BF7\u4E0D\u8981\u518D\u7528 Read \u91CD\u65B0\u8BFB\u53D6\u5B83\u2014\u2014\u5B83\u5DF2\u4E0D\u53EF\u7528\u3002\u8BF7\u57FA\u4E8E\u73B0\u6709\u6587\u5B57\u4FE1\u606F\u7EE7\u7EED\uFF1B\u82E5\u786E\u5B9E\u9700\u8981\u8BE5\u56FE\uFF0C\u8BF7\u63D0\u793A\u7528\u6237\u91CD\u65B0\u4E0A\u4F20\u4E00\u5F20\u66F4\u5C0F\u7684\u622A\u56FE\u3002");return}if(i.type==="assistant"&&Array.isArray(i.message?.content)){const e=!!i.parent_tool_use_id,s=i.parent_tool_use_id||"main";for(const u of i.message.content){if(u.type!=="tool_use")continue;if(!e&&(this._loopTurnToolCalls++,this._loopTurnToolCalls>LOOP_MAX_TURN_TOOLCALLS)){this._tripLoopBreaker(`\u672C\u8F6E\u5DE5\u5177\u8C03\u7528\u5DF2\u8FBE ${this._loopTurnToolCalls} \u6B21\u5E76\u63D2\u5165\u68C0\u67E5\u70B9\u3002\u82E5\u4ECD\u5728\u6B63\u5E38\u63A8\u8FDB\uFF0C\u8BF7\u6982\u8FF0\u5F53\u524D\u8FDB\u5C55\u540E\u7EE7\u7EED\uFF1B\u82E5\u5728\u91CD\u590D\u540C\u7C7B\u64CD\u4F5C\u800C\u6CA1\u6709\u8FDB\u5C55\uFF0C\u8BF7\u6362\u4E00\u79CD\u601D\u8DEF\uFF0C\u6216\u5148\u5411\u7528\u6237\u6C47\u62A5\u518D\u7B49\u5F85\u6307\u793A\u3002`);return}const f=`${s}:${u.name}:${this._hashInput(u.input)}`,l=(this._loopSigCounts.get(f)||0)+1;if(this._loopSigCounts.set(f,l),l>=LOOP_MAX_IDENTICAL_CALLS){this._tripLoopBreaker(`\u5DE5\u5177\u300C${u.name}\u300D\u5DF2\u7528\u5B8C\u5168\u76F8\u540C\u7684\u53C2\u6570\u8C03\u7528 ${l} \u6B21\uFF0C\u7591\u4F3C\u9677\u5165\u6B7B\u5FAA\u73AF\u3002\u8BF7\u505C\u6B62\u91CD\u590D\u8BE5\u8C03\u7528\uFF0C\u6539\u7528\u4E0D\u540C\u53C2\u6570/\u4E0D\u540C\u5DE5\u5177\uFF0C\u6216\u8DF3\u8FC7\u8FD9\u4E00\u6B65\u7EE7\u7EED\u3002`);return}}}}_hashInput(i){let n;try{n=JSON.stringify(stripHeavyPayload(i))}catch{n=String(i)}n.length>4096&&(n=n.slice(0,4096));let t=5381;for(let e=0;e<n.length;e++)t=(t<<5)+t+n.charCodeAt(e)|0;return t.toString(36)}_tripLoopBreaker(i){if(this._loopTripped=!0,console.warn("[agent] \u{1F50C} \u6B7B\u5FAA\u73AF\u7194\u65AD:",i),this._loopAutoRecover>=LOOP_MAX_AUTO_RECOVER){this._pendingSteer=null,this.emit("agent:message",{type:"system",subtype:"warning",message:"\u26A0\uFE0F \u591A\u6B21\u81EA\u52A8\u7EA0\u504F\u4ECD\u672A\u8DF3\u51FA\u5FAA\u73AF\uFF0C\u5DF2\u505C\u6B62\u4EE5\u4FDD\u62A4 session \u989D\u5EA6\u3002\u8BF7 /clear \u91CD\u5F00\u6216\u6362\u4E2A\u95EE\u6CD5\u3002"}),this.interrupt();return}this._loopAutoRecover++,this._pendingSteer=i,this.emit("agent:message",{type:"system",subtype:"warning",message:`\u26A0\uFE0F \u7194\u65AD\u4FDD\u62A4\uFF08\u7B2C ${this._loopAutoRecover} \u6B21\u81EA\u52A8\u7EA0\u504F\uFF09\uFF1A${i}`}),this.interrupt()}_flushPendingSteer(){if(!this._pendingSteer)return;const i=this._pendingSteer;this._pendingSteer=null,setTimeout((()=>{!this._busy&&this.alive&&this.query(i,{internal:!0}).catch((()=>{}))}),600)}setFollowUp({enabled:i,intervalMinutes:n}={}){if(typeof i=="boolean"&&(this._followEnabled=i),n!=null){const t=Math.max(1,Math.min(180,Number(n)||15));this._followIntervalMs=Math.round(t*60*1e3)}return this._followEnabled?this._busy||this._maybeScheduleFollowUp():(this._cancelFollowUp(),this._followCount=0),this.emit("agent:message",{type:"system",subtype:"info",message:this._followEnabled?`\u{1F504} \u81EA\u52A8\u8DDF\u8FDB\u5DF2\u5F00\u542F\uFF1A\u6BCF ${Math.round(this._followIntervalMs/6e4)} \u5206\u949F\u81EA\u52A8\u67E5\u4E00\u6B21\u8FDB\u5EA6\u5E76\u6C47\u62A5\uFF08\u6700\u591A ${this._followMax} \u6B21\uFF1BAI \u5224\u65AD\u5168\u90E8\u5B8C\u6210\u4F1A\u81EA\u52A8\u505C\uFF09\u3002`:"\u{1F504} \u81EA\u52A8\u8DDF\u8FDB\u5DF2\u5173\u95ED\u3002"}),this.followUpState()}followUpState(){return{enabled:this._followEnabled,intervalMinutes:Math.round(this._followIntervalMs/6e4),max:this._followMax,count:this._followCount}}_cancelFollowUp(){this._followTimer&&(clearTimeout(this._followTimer),this._followTimer=null)}_cancelRelay(){this._relayTimer&&(clearTimeout(this._relayTimer),this._relayTimer=null)}_maybeRelayDraft(){!this.alive||this._relayTimer||(this._relayTimer=setTimeout((()=>{if(this._relayTimer=null,this._busy||!this.alive)return;let i=null;try{i=nextAutoSendDraft(this.id)}catch{return}if(!i)return;try{removeDraft(i.id)}catch{}const n=buildDraftPrompt(i);n.trim()&&(this.emit("agent:message",{type:"system",subtype:"info",message:"\u{1F4E5} \u81EA\u52A8\u63A5\u529B\uFF1A\u4E0A\u4E00\u8F6E\u5DF2\u5B8C\u6210\uFF0C\u53D1\u51FA\u4E0B\u9762\u8FD9\u6761\u8349\u7A3F"}),this.emit("agent:message",{type:"user",content:draftDisplayText(i)||n,timestamp:Date.now()}),this.emit("draft-relayed",{id:i.id,sessionId:this.id}),this.lastInputTime=Date.now(),this.query(n).catch((()=>{})))}),RELAY_DELAY_MS),this._relayTimer.unref&&this._relayTimer.unref())}_maybeScheduleFollowUp(){if(this._cancelFollowUp(),!(!this._followEnabled||!this.alive)){if(this._followStopSignal){this._followStopSignal=!1,this._followCount=0,this.emit("agent:message",{type:"system",subtype:"info",message:"\u{1F504} AI \u5DF2\u786E\u8BA4\u4EFB\u52A1\u5168\u90E8\u5B8C\u6210\uFF0C\u81EA\u52A8\u8DDF\u8FDB\u505C\u6B62\u3002"});return}if(this._followCount>=this._followMax){this.emit("agent:message",{type:"system",subtype:"info",message:`\u{1F504} \u81EA\u52A8\u8DDF\u8FDB\u5DF2\u8FDE\u7EED ${this._followMax} \u6B21\uFF0C\u6682\u505C\uFF08\u9632\u7A7A\u8F6C\u70E7\u989D\u5EA6\uFF09\u3002\u9700\u8981\u7EE7\u7EED\u53EF\u624B\u52A8\u95EE\u4E00\u53E5\u6216\u91CD\u5F00\u3002`});return}this._followTimer=setTimeout((()=>{this._followTimer=null,!(this._busy||!this.alive||!this._followEnabled)&&(this._followCount++,this.emit("agent:message",{type:"system",subtype:"info",message:`\u{1F504} \u81EA\u52A8\u8DDF\u8FDB\uFF08\u7B2C ${this._followCount}/${this._followMax} \u6B21\uFF09\uFF1A\u8BA9 AI \u67E5\u770B\u8FDB\u5EA6\u2026`}),this.query(FOLLOW_UP_PROMPT,{internal:!0}).catch((()=>{})))}),this._followIntervalMs)}}_startStallWatchdog(){this._stopStallWatchdog(),this._watchdogTimer=setInterval((()=>{if(!this._busy){this._stopStallWatchdog();return}if(this._awaitingTool)return;const i=Date.now()-this._lastActivityAt;if(i>=STALL_WATCHDOG_MS){const n=Math.round(i/1e3);console.warn(`[agent] \u23F1 \u505C\u6446\u770B\u95E8\u72D7\u89E6\u53D1\uFF1A\u7B49\u5F85\u6A21\u578B\u54CD\u5E94\u5DF2 ${n}s \u65E0\u4EFB\u4F55\u6D88\u606F\uFF0C\u5F3A\u5236\u4E2D\u65AD`),this.emit("agent:message",{type:"system",subtype:"warning",message:`\u23F1 \u68C0\u6D4B\u5230\u4F1A\u8BDD\u505C\u6446\uFF08\u7B49\u5F85\u6A21\u578B\u54CD\u5E94 ${n}s \u65E0\u54CD\u5E94\uFF0C\u7591\u4F3C API \u4F20\u8F93\u5C42\u91CD\u8BD5\u5361\u4F4F\uFF09\uFF0C\u5DF2\u5F3A\u5236\u4E2D\u65AD\u672C\u56DE\u5408\u3002\u8BF7\u91CD\u8BD5\u6216\u7A0D\u540E\u518D\u8BD5\u3002`}),this._stopStallWatchdog(),this.interrupt()}}),STALL_CHECK_INTERVAL_MS),this._watchdogTimer.unref&&this._watchdogTimer.unref()}_stopStallWatchdog(){this._watchdogTimer&&(clearInterval(this._watchdogTimer),this._watchdogTimer=null)}_onControlRequest(i){const n=i.request||{},t=i.request_id;if(n.subtype!=="can_use_tool"){this._writeStdin({type:"control_response",response:{subtype:"error",request_id:t,error:`myhi \u4E0D\u652F\u6301 ${n.subtype}`}});return}if(n.tool_name==="AskUserQuestion"||n.tool_name==="ExitPlanMode")return this._openInteraction({id:t,kind:n.tool_name==="AskUserQuestion"?"ask":"plan",input:n.input||{},toolUseId:n.tool_use_id});this._ctlReply(t,{behavior:"deny",message:"\u5F53\u524D\u6743\u9650\u6A21\u5F0F\u4E0D\u5141\u8BB8\u6B64\u64CD\u4F5C\uFF08myhi \u65E0\u4EBA\u503C\u5B88\uFF0C\u65E0\u6CD5\u9010\u9879\u6388\u6743\uFF09\u3002\u8BF7\u57FA\u4E8E\u73B0\u72B6\u7EE7\u7EED\uFF0C\u6216\u5728\u56DE\u590D\u91CC\u8BF4\u660E\u9700\u8981\u7528\u6237\u5207\u6362\u5230\u81EA\u52A8\u6267\u884C\u3002"})}_ctlReply(i,n){return this._writeStdin({type:"control_response",response:{subtype:"success",request_id:i,response:n}})}get pendingInteractions(){return[...this._interactions?.values()||[]].map((i=>i.view))}_openInteraction(i){this._interactions||(this._interactions=new Map);const n=redactDeep(this._pseudo?.enabled?redactDeep(i.input,this._pseudo.restore):i.input,this._redactor);i.view={id:i.id,kind:i.kind,toolUseId:i.toolUseId,at:Date.now(),questions:i.kind==="ask"?n.questions||[]:void 0,plan:i.kind==="plan"?String(n.plan||""):void 0};const t=this._followEnabled?INTERACTION_WAIT_FOLLOW_MS:INTERACTION_WAIT_MS;i.view.deadline=Date.now()+t,i.timer=setTimeout((()=>this.respondInteraction(i.id,{skip:!0,timeout:!0},"\u7CFB\u7EDF")),t),i.timer.unref&&i.timer.unref(),this._interactions.set(i.id,i),this.emit("agent:interaction",i.view)}respondInteraction(i,n={},t=""){const e=this._interactions?.get(i);if(!e)return{ok:!1,error:"\u8FD9\u4E2A\u63D0\u95EE\u5DF2\u7ECF\u5904\u7406\u8FC7\u4E86"};clearTimeout(e.timer),this._interactions.delete(i);const s=f=>this._pseudo?.enabled?this._pseudo.pseudonymize(String(f)).text:String(f);let u;if(e.kind==="ask")if(n.skip||!n.answers||!Object.keys(n.answers).length)this._ctlReply(i,{behavior:"deny",message:n.timeout?"\u7528\u6237\u8F83\u957F\u65F6\u95F4\u6CA1\u6709\u4F5C\u7B54\u3002\u8BF7\u6309\u4F60\u7684\u6700\u4F73\u5224\u65AD\u7EE7\u7EED\uFF0C\u5E76\u5728\u56DE\u590D\u91CC\u8BF4\u660E\u4F60\u505A\u4E86\u54EA\u4E9B\u5047\u8BBE\u3002":"\u7528\u6237\u9009\u62E9\u4E0D\u56DE\u7B54\u8FD9\u4E2A\u95EE\u9898\u3002\u8BF7\u6309\u4F60\u7684\u6700\u4F73\u5224\u65AD\u7EE7\u7EED\uFF0C\u5E76\u5728\u56DE\u590D\u91CC\u8BF4\u660E\u4F60\u505A\u4E86\u54EA\u4E9B\u5047\u8BBE\u3002"}),u=n.timeout?"\u23ED \u63D0\u95EE\u7B49\u5F85\u8D85\u65F6\uFF0CAI \u5C06\u6309\u6700\u4F73\u5224\u65AD\u7EE7\u7EED":`\u23ED ${t} \u8DF3\u8FC7\u4E86\u63D0\u95EE\uFF0CAI \u5C06\u6309\u6700\u4F73\u5224\u65AD\u7EE7\u7EED`;else{const f={},l=e.input.questions||[],o=e.view.questions||[];o.forEach(((c,r)=>{const a=n.answers[c.question];a!==void 0&&l[r]&&(f[l[r].question]=s(a))})),this._ctlReply(i,{behavior:"allow",updatedInput:{...e.input,answers:f}}),u=`\u{1F4DD} ${t} \u5DF2\u56DE\u7B54\uFF1A`+o.map((c=>`${c.header||c.question}\uFF1D${n.answers[c.question]??"\uFF08\u672A\u7B54\uFF09"}`)).join("\uFF1B")}else if(n.approve)this._ctlReply(i,{behavior:"allow",updatedInput:e.input,updatedPermissions:[{type:"setMode",mode:"bypassPermissions",destination:"session"}]}),u=`\u2705 ${t} \u6279\u51C6\u4E86\u65B9\u6848\uFF0CAI \u5F00\u59CB\u6267\u884C`;else{const f=String(n.feedback||"").trim();this._ctlReply(i,{behavior:"deny",message:n.timeout?"\u7528\u6237\u8F83\u957F\u65F6\u95F4\u6CA1\u6709\u5BA1\u6279\u65B9\u6848\uFF0C\u6682\u4E0D\u6267\u884C\u3002\u4FDD\u6301\u8BA1\u5212\u6A21\u5F0F\uFF0C\u7B49\u5F85\u7528\u6237\u56DE\u590D\u3002":`\u7528\u6237\u5E0C\u671B\u4FEE\u6539\u65B9\u6848${f?"\uFF1A"+s(f):""}\u3002\u8BF7\u6309\u610F\u89C1\u4FEE\u6539\u540E\u91CD\u65B0\u7528 ExitPlanMode \u63D0\u4EA4\u3002`}),u=n.timeout?"\u23ED \u65B9\u6848\u5BA1\u6279\u7B49\u5F85\u8D85\u65F6\uFF0C\u6682\u4E0D\u6267\u884C":`\u270F\uFE0F ${t} \u8981\u6C42\u4FEE\u6539\u65B9\u6848${f?"\uFF1A"+f:""}`}return this.emit("agent:interaction-closed",{id:i,kind:e.kind}),this.emit("agent:message",{type:"system",subtype:"info",message:u}),{ok:!0}}_dropInteractions(){if(this._interactions?.size){for(const i of this._interactions.values())clearTimeout(i.timer),this.emit("agent:interaction-closed",{id:i.id,kind:i.kind});this._interactions.clear()}}_hardKillTree(i){if(i)try{if(process.platform==="win32")(0,external_child_process_namespaceObject.execSync)(`taskkill /PID ${i} /F /T`,{stdio:"pipe",timeout:5e3});else{try{process.kill(i,"SIGTERM")}catch{}setTimeout((()=>{try{process.kill(i,0)}catch{return}try{process.kill(i,"SIGKILL")}catch{}}),1e3)}}catch{}}get canInject(){return!!this._injectable&&!!this._proc&&this._busy}inject(i,{display:n}={}){if(!this._injectable)return{ok:!1,error:"\u5F53\u524D Claude \u7248\u672C\u4E0D\u652F\u6301\u63D2\u8BDD\uFF0C\u8BF7\u5347\u7EA7 Claude Code \u540E\u91CD\u8BD5"};if(!this._proc||!this._busy)return{ok:!1,error:"AI \u73B0\u5728\u6CA1\u5728\u5E72\u6D3B\uFF0C\u76F4\u63A5\u53D1\u9001\u5C31\u884C"};if(this._interactions?.size)return{ok:!1,error:"AI \u6B63\u5728\u7B49\u4F60\u56DE\u7B54\u63D0\u95EE / \u5BA1\u6279\u65B9\u6848\uFF0C\u8BF7\u5148\u5728\u5F39\u7A97\u91CC\u5904\u7406"};if(i=typeof i=="string"?i.trim():"",!i)return{ok:!1,error:"\u63D2\u8BDD\u5185\u5BB9\u662F\u7A7A\u7684"};if(i.startsWith("/"))return{ok:!1,error:"\u63D2\u8BDD\u4E0D\u652F\u6301 / \u547D\u4EE4\uFF0C\u8BF7\u7B49 AI \u5E72\u5B8C\u518D\u53D1"};let t=i;if(this._pseudo?.enabled){const l=this._pseudo.pseudonymize(i);t=l.text;const o=this.claudeSessionId||this.id;saveMap(o,this._pseudoMap),l.count>0&&appendAudit(o,{ts:Date.now(),level:this._pseudo.level,maskedCount:l.count,byType:l.byType,sentToModel:l.text,inject:!0})}const e=(0,external_crypto_.randomUUID)();if(!this._writeStdin({type:"user",uuid:e,message:{role:"user",content:t}}))return{ok:!1,error:"Claude \u8FDB\u7A0B\u4E0D\u53EF\u5199\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5"};this._injected||(this._injected=new Map);const s=Date.now(),u=redactDeep(n||i,this._redactor),f={type:"user",content:u,timestamp:s,inject:{id:e,state:"pending"}};return this._injected.set(e,f),this._history.push(f),this.emit("agent:message",{type:"user",content:u,timestamp:s,inject:{id:e,state:"pending"}}),this.lastInputTime=s,{ok:!0,id:e}}_onReplay(i){const n=i.uuid&&this._injected?.get(i.uuid);n&&(this._injected.delete(i.uuid),n.inject.state="seen",this.emit("agent:message",{type:"system",subtype:"inject_state",id:i.uuid,state:"seen"}),this._injected.size||clearTimeout(this._injectWaitTimer)),this._busy||(this._busy=!0,this._interrupted=!1,this.emit("agent:busy",!0),this._lastActivityAt=Date.now(),this._awaitingTool=!1,this._startStallWatchdog())}refreshSkills(){if(!this._proc)return!1;if(this._busy)return this._skillsDirty=!0,!0;this._skillsDirty=!1,this._expectExit=!0;const i=this._proc.pid;return this._proc=null,this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._hardKillTree(i),this.emit("agent:message",{type:"system",subtype:"info",message:"\u{1F9E0} \u6280\u80FD\u6709\u53D8\u5316\uFF1A\u4E0B\u4E00\u8F6E AI \u4F1A\u91CD\u65B0\u52A0\u8F7D\u6280\u80FD\uFF08\u63A5\u7740\u539F\u6765\u7684\u5BF9\u8BDD\uFF09"}),!0}_dropInjected(i){if(clearTimeout(this._injectWaitTimer),!!this._injected?.size){for(const[n,t]of this._injected)t.inject.state="dropped",this.emit("agent:message",{type:"system",subtype:"inject_state",id:n,state:"dropped",reason:i});this._injected.clear()}}interrupt(){if(this._dropInteractions(),this._describing){this._describeAborted=!0,this._describing.abort();return}if(!this._proc||!this._busy)return;this._interrupted=!0;const i=this._proc.pid,n=this._proc,t=Date.now();this._injected?.size&&this.emit("agent:message",{type:"system",subtype:"info",message:"\u26A1 \u4F60\u521A\u63D2\u7684\u8BDD\u5DF2\u7ECF\u6392\u8FDB AI \u7684\u961F\u5217\uFF0C\u4E2D\u65AD\u540E\u5B83\u4F1A\u63A5\u7740\u5904\u7406\uFF1B\u4E0D\u9700\u8981\u7684\u8BDD\u7B49\u5B83\u5F00\u59CB\u540E\u518D\u70B9\u4E00\u6B21\u505C\u6B62"});const s=this._writeStdin({type:"control_request",request_id:`interrupt-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,request:{subtype:"interrupt"}})?1500:0;setTimeout((()=>{this._busy&&this._proc===n&&((this._lastResultAt||0)>=t||(console.log(`[agent] graceful interrupt \u8D85\u65F6\uFF0C\u5F3A\u5236\u7ED3\u675F\u8FDB\u7A0B\u6811 PID ${i}`),this._hardKillTree(i)))}),s),this.emit("agent:message",{type:"system",subtype:"interrupted",message:"\u67E5\u8BE2\u5DF2\u4E2D\u65AD"})}kill(){if(this._dropInteractions(),this._dropInjected("\u4F1A\u8BDD\u5DF2\u7EC8\u6B62"),this.alive=!1,this._cancelRelay(),this._cancelFollowUp(),this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._proc&&(this._hardKillTree(this._proc.pid),this._proc=null),this._pendingReject){try{this._pendingReject(new Error("\u4F1A\u8BDD\u5DF2\u7EC8\u6B62"))}catch{}this._pendingResolve=null,this._pendingReject=null}this._busy=!1}_readTranscriptCtx(){if(!this.claudeSessionId)return null;try{const i=(0,external_path_.join)((0,external_os_.homedir)(),".claude","projects");if(!(0,external_fs_.existsSync)(i))return null;for(const n of(0,external_fs_.readdirSync)(i,{withFileTypes:!0})){if(!n.isDirectory())continue;const t=(0,external_path_.join)(i,n.name,this.claudeSessionId+".jsonl");if(!(0,external_fs_.existsSync)(t))continue;const e=(0,external_fs_.statSync)(t).size,s=Math.min(e,65536),u=Buffer.alloc(s),f=(0,external_fs_.openSync)(t,"r");try{(0,external_fs_.readSync)(f,u,0,s,e-s)}finally{(0,external_fs_.closeSync)(f)}const l=u.toString("utf8").split(`
|
|
400
|
+
`)}))})),this._proc.on("close",(o=>{if(f()){console.log(`[agent] \u65E7\u8FDB\u7A0B\u9000\u51FA (code ${o})\uFF0C\u5DF2\u88AB\u65B0\u8FDB\u7A0B\u66FF\u6362\uFF0C\u5FFD\u7565`);return}if(!this._interrupted&&this._buffer.trim())try{const c=JSON.parse(this._buffer.trim());this._handleMessage(c)}catch{}if(this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._stopStallWatchdog(),this._proc=null,this._buffer="",this._dropInteractions(),this._dropInjected("Claude \u8FDB\u7A0B\u5DF2\u9000\u51FA\uFF0C\u8FD9\u6761\u63D2\u8BDD\u6CA1\u6709\u9001\u8FBE"),console.log(`[agent] \u8FDB\u7A0B\u9000\u51FA (code ${o}), \u4F1A\u8BDD: ${this.claudeSessionId||"?"}`),this._busy&&(this._busy=!1,this._interrupted=!1,this.emit("agent:busy",!1),this._pendingReject&&(this._pendingReject(new Error(`Claude \u8FDB\u7A0B\u9000\u51FA (code ${o})`)),this._pendingResolve=null,this._pendingReject=null)),this._flushPendingSteer(),this._spawnFailed){this._spawnFailed=!1;return}if(this._expectExit){this._expectExit=!1;return}this.alive&&o!==0&&o!==null&&this.emit("agent:error",{message:`Claude \u8FDB\u7A0B\u5F02\u5E38\u9000\u51FA (code ${o})\uFF0C\u4E0B\u6B21\u67E5\u8BE2\u5C06\u81EA\u52A8\u91CD\u542F`})})),this._proc.on("error",(o=>{f()||(this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._stopStallWatchdog(),this._proc=null,this._busy=!1,this.emit("agent:busy",!1),this._spawnFailed=!0,this.emit("agent:error",{message:o.code==="ENOENT"?CLAUDE_MISSING_MSG:`\u542F\u52A8 Claude \u5931\u8D25: ${o.message}`}),o.reported=!0,this._pendingReject&&(this._pendingReject(o),this._pendingResolve=null,this._pendingReject=null))})),this._keepAliveTimer=setInterval((()=>{this._writeStdin({type:"keep_alive"})}),3e4)}async query(i,{internal:n=!1,from:t=null,display:e=null,actor:s=null}={}){if(this._busy){this.emit("agent:error",{message:"\u6B63\u5728\u5904\u7406\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u5B8C\u6210"});return}if(n||(this._followCount=0,this._followStopSignal=!1,this._cancelFollowUp()),i==="/clear"){this.reset();const o=[CLEAR_WHERE[s?.where],s?.device].filter(Boolean).join(" \xB7 "),c=s?.via==="button"?"\u70B9\u4E86\u300C\u6E05\u9664\u300D":"\u53D1\u9001\u4E86 /clear",r=s?`${s.name||"\u7528\u6237"}${o?`\uFF08${o}\uFF09`:""}${c}\uFF0C`:"";console.log(`[clear] \u4F1A\u8BDD ${this.id}\u300C${this.title||""}\u300D\u88AB\u6E05\u9664\uFF1A${s?`${s.name||"?"} / ${CLEAR_WHERE[s.where]||"\u672A\u77E5\u9875\u9762"} / ${s.device||"?"} / ${s.via}`:"\u5185\u90E8\u8C03\u7528"}`),this.emit("agent:message",{type:"system",subtype:"info",cleared:!0,message:`${r}\u5DF2\u5F00\u59CB\u65B0\u5BF9\u8BDD\uFF1AAI \u4E0D\u518D\u8BB0\u5F97\u4E4B\u524D\u804A\u8FC7\u7684\u5185\u5BB9\uFF08\u9879\u76EE\u6587\u4EF6\u4E0D\u53D7\u5F71\u54CD\uFF09`});return}const u=i.match(/^\/resume\s+(\S+)/);if(u){if(this._proc){this._expectExit=!0;try{this._proc.kill("SIGTERM")}catch{}this._proc=null}this.claudeSessionId=u[1],this._history=[],this._buffer="",this._loadResumedHistory(),this.emit("agent:message",{type:"system",subtype:"info",message:`\u5DF2\u5207\u6362\u5230\u4F1A\u8BDD ${u[1].slice(0,8)}...\uFF0C\u4E0B\u6B21\u63D0\u95EE\u5C06\u6062\u590D\u8BE5\u5BF9\u8BDD`});return}const f=i.match(/^\/model\s+(\S+)/);if(f){if(this.modelId=f[1]==="default"?null:f[1],this.emit("settings-changed"),this._proc){this._expectExit=!0;try{this._proc.kill("SIGTERM")}catch{}this._proc=null}const o=this.modelId||sceneModel("main");this.emit("agent:message",{type:"system",subtype:"info",message:this.modelId?`\u6A21\u578B\u5DF2\u5207\u6362\u4E3A ${this.modelId}`:`\u5DF2\u6062\u590D\u9ED8\u8BA4\u6A21\u578B${o?`\uFF08${o}\uFF09`:"\uFF08Claude Code \u9ED8\u8BA4\uFF09"}`});return}if(i==="/plan"||i.startsWith("/plan ")){if(this.permissionMode==="plan"){if(this.permissionMode=normalizePermissionMode(this._prePlanMode),this._prePlanMode=null,this._proc){this._expectExit=!0;try{this._proc.kill("SIGTERM")}catch{}this._proc=null}this.emit("agent:message",{type:"system",subtype:"info",message:"\u5DF2\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"})}else{if(this._prePlanMode=this.permissionMode,this.permissionMode="plan",this._proc){this._expectExit=!0;try{this._proc.kill("SIGTERM")}catch{}this._proc=null}this.emit("agent:message",{type:"system",subtype:"info",message:"\u5DF2\u8FDB\u5165\u8BA1\u5212\u6A21\u5F0F\uFF08\u53EA\u89C4\u5212\u4E0D\u6267\u884C\uFF09"});const c=i.slice(5).trim();if(c){setTimeout((()=>this.query(c)),500);return}}return}if(i.startsWith("/rename")){this.emit("agent:message",{type:"system",subtype:"info",message:"\u4F1A\u8BDD\u5DF2\u547D\u540D"});return}this._busy=!0,this._interrupted=!1,this.emit("agent:busy",!0),this._loopSigCounts.clear(),this._loopPoisonHits=0,this._loopTurnToolCalls=0,this._loopTripped=!1,n||(this._loopAutoRecover=0),this._redactor=buildRedactor(),this._pseudoMap||(this._pseudoMap=loadMap(this.claudeSessionId||this.id)),this._pseudo=buildPseudonymizer(this.cwd,this._pseudoMap),this._lastActivityAt=Date.now(),this._awaitingTool=!1,this._startStallWatchdog();const l=redactDeep(typeof e=="string"&&e.trim()?e.trim().slice(0,500):i,this._redactor);this._history.push({type:"user",content:l,timestamp:Date.now()}),t&&this.emit("agent:message",{type:"user",content:l,timestamp:Date.now(),from:t}),!this.firstUserText&&typeof l=="string"&&!l.startsWith("/")&&(this.firstUserText=l.trim().slice(0,160));try{i=await this._prepareImages(i)}catch(o){if(o.name==="AbortError"||this._describeAborted){this._describeAborted=!1,this._busy=!1,this._stopStallWatchdog(),this.emit("agent:busy",!1),this.emit("agent:message",{type:"system",subtype:"interrupted"});return}console.warn("[\u770B\u56FE] \u51FA\u9519\uFF0C\u6309\u539F\u6837\u53D1\u9001:",o.message)}return this._lastActivityAt=Date.now(),this._proc||(_interactiveCap===null&&await probeInteractive(),this._spawnProcess()),new Promise(((o,c)=>{this._pendingResolve=o,this._pendingReject=c,i.startsWith("/")&&(this._slashTimeout=setTimeout((()=>{this._busy&&(this._busy=!1,this._interrupted=!1,this.emit("agent:busy",!1),this.emit("agent:message",{type:"system",subtype:"info",message:`\u547D\u4EE4 ${i} \u5DF2\u53D1\u9001`}),this._pendingResolve&&(this._pendingResolve(0),this._pendingResolve=null,this._pendingReject=null))}),3e4));let r=i;if(this._pseudo?.enabled){const h=this._pseudo.pseudonymize(i);r=h.text;const m=this.claudeSessionId||this.id;saveMap(m,this._pseudoMap),h.count>0&&(appendAudit(m,{ts:Date.now(),level:this._pseudo.level,maskedCount:h.count,byType:h.byType,sentToModel:h.text}),this.emit("agent:message",{type:"system",subtype:"info",message:`\u{1F6E1} \u9690\u79C1\u62A4\u680F\uFF1A\u672C\u8F6E\u5DF2\u8131\u654F ${h.count} \u5904\u654F\u611F\u4FE1\u606F\uFF0C\u6A21\u578B\u53EA\u770B\u5230\u5360\u4F4D\u7B26\uFF08\u6620\u5C04\u8868\u7559\u672C\u673A\u3001\u53EF\u9006\u8FD8\u539F\uFF09\u3002`}))}this._writeStdin({type:"user",uuid:(0,external_crypto_.randomUUID)(),message:{role:"user",content:r}})||(this._busy=!1,this.emit("agent:busy",!1),this._pendingResolve=null,this._pendingReject=null,c(new Error("Claude \u8FDB\u7A0B\u4E0D\u53EF\u5199")))}))}_handleMessage(i){const n=!!this.claudeSessionId;if(this._lastActivityAt=Date.now(),i.type==="assistant"&&Array.isArray(i.message?.content)?(!this._busy&&!i.parent_tool_use_id&&(this._busy=!0,this._interrupted=!1,this.emit("agent:busy",!0),this._lastActivityAt=Date.now(),this._startStallWatchdog()),i.message.content.some((l=>l.type==="tool_use"))&&(this._awaitingTool=!0)):i.type==="user"&&(this._awaitingTool=!1),i.type==="control_request"){this._onControlRequest(i);return}if(i.type==="control_response")return;if(i.type==="user"&&i.isReplay){this._onReplay(i);return}if(i.type==="system"&&i.subtype==="status"&&i.permissionMode){const l=normalizePermissionMode(i.permissionMode);VALID_PERMISSION_MODES.has(i.permissionMode)&&l!==this.permissionMode&&(this.permissionMode=l,l!=="plan"&&(this._prePlanMode=null),this.emit("mode-changed",l));return}if(i.session_id&&!this.claudeSessionId&&(this.claudeSessionId=i.session_id),i.type==="system"&&i.subtype==="init"&&i.session_id&&(this.claudeSessionId=i.session_id),!n&&this.claudeSessionId&&this.emit("session-id",this.claudeSessionId),i.type==="system"&&i.subtype==="init"&&this.permissionMode==="bypassPermissions"&&i.permissionMode&&i.permissionMode!=="bypassPermissions"){const l=i.permissionMode;this.reset(),this.emit("agent:message",{type:"system",subtype:"warning",message:`\u26A0\uFE0F \u8FD9\u4E2A\u4F1A\u8BDD\u88AB --resume \u5E26\u56DE\u4E86\u300C${l}\u300D\u6A21\u5F0F\uFF08\u975E bypass\uFF0C\u4F1A\u62E6\u5199/\u5220\u4E14\u65E0\u6CD5\u8FD0\u884C\u65F6\u63D0\u6743\uFF0C\u70B9\u300C\u9000\u51FA\u8BA1\u5212\u300D\u4E5F\u9003\u4E0D\u6389\uFF09\u3002\u5DF2\u81EA\u52A8\u65AD\u5F00\u65E7\u4F1A\u8BDD\u94FE\u3001\u91CD\u5F00\u4E3A\u5E72\u51C0\u7684 bypass \u4F1A\u8BDD\u2014\u2014\u8BF7\u91CD\u53D1\u4F60\u521A\u624D\u7684\u6307\u4EE4\uFF0C\u8FD9\u6B21\u4F1A\u76F4\u63A5\u6267\u884C\u3002`});return}const t=this._pseudo?.enabled?redactDeep(i,this._pseudo.restore):i,e=redactDeep(t,this._redactor),s=stripHeavyPayload({...e,timestamp:Date.now()}),u=JSON.stringify(s);this._followEnabled&&u.includes("[\u8DDF\u8FDB\u5B8C\u6210]")&&(this._followStopSignal=!0),u.length>10240&&(s._truncated=!0),this._history.push(s);const f=500;if(this._history.length>f&&(this._history=this._history.slice(-f)),this._trackImagePressure(u),this._checkDeathLoop(i,u),i.type==="rate_limit_event"&&i.rate_limit_info&&(this._usage.rateLimitInfo=i.rate_limit_info),i.type==="result"){const l=this._usageBase;if(this._procQueryCount=(this._procQueryCount||0)+1,this._usage.queryCount=l.queryCount+this._procQueryCount,i.total_cost_usd&&(this._usage.totalCostUSD=l.totalCostUSD+i.total_cost_usd),i.usage&&(this._usage.totalInputTokens=l.totalInputTokens+(i.usage.input_tokens||0),this._usage.totalOutputTokens=l.totalOutputTokens+(i.usage.output_tokens||0),this._usage.totalCacheReadTokens=l.totalCacheReadTokens+(i.usage.cache_read_input_tokens||0),this._usage.totalCacheCreationTokens=l.totalCacheCreationTokens+(i.usage.cache_creation_input_tokens||0)),i.modelUsage)for(const[o,c]of Object.entries(i.modelUsage)){const r=l.modelUsage[o]||{inputTokens:0,outputTokens:0,costUSD:0};this._usage.modelUsage[o]={inputTokens:r.inputTokens+(c.inputTokens||0),outputTokens:r.outputTokens+(c.outputTokens||0),costUSD:r.costUSD+(c.costUSD||0)}}}{let l=i.type==="assistant"?i.message?.usage:null;if(i.type==="result"&&(l=this._readTranscriptCtx()||l),l){const o=(l.input_tokens||0)+(l.cache_read_input_tokens||0)+(l.cache_creation_input_tokens||0);(o>this._contextTokens||this._contextTokens>0&&o<this._contextTokens*.5)&&(this._contextTokens=o)}}if(i.type==="result"&&(e.ctxTokens=this._contextTokens),i.type==="result"&&this._injected?.size&&(e.injectPending=!0),this.emit("agent:message",e),i.type==="result"){this._slashTimeout&&(clearTimeout(this._slashTimeout),this._slashTimeout=null),this._stopStallWatchdog();const l=!this._interrupted&&!i.is_error;if(this._pendingResolve&&(this._pendingResolve(0),this._pendingResolve=null,this._pendingReject=null),this._lastResultAt=Date.now(),this._injected?.size){this._interrupted=!1,this._lastActivityAt=Date.now(),this._startStallWatchdog(),clearTimeout(this._injectWaitTimer),this._injectWaitTimer=setTimeout((()=>{!this._injected?.size||!this._busy||(this._dropInjected("AI \u6CA1\u6709\u63A5\u6536\u8FD9\u6761\u63D2\u8BDD\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001"),this._busy=!1,this.emit("agent:busy",!1))}),INJECT_FOLLOW_WAIT_MS);return}this._busy=!1,this._interrupted=!1,this.emit("agent:busy",!1),this._skillsDirty&&setTimeout((()=>{this._busy||this.refreshSkills()}),0),this._flushPendingSteer(),l&&this._maybeRelayDraft(),this._maybeScheduleFollowUp()}}_trackImagePressure(i){const n=(i.match(/"type":"image"/g)||[]).length;n&&(this._imageBlockCount+=n,this._imageBlockCount>=this._imageNudgeAt&&(this._imageNudgeAt+=IMAGE_NUDGE_STEP,this.emit("agent:message",{type:"system",subtype:"warning",message:`\u2139\uFE0F \u672C\u4F1A\u8BDD\u5DF2\u7D2F\u79EF\u7EA6 ${this._imageBlockCount} \u5F20\u56FE\u7247\u3002\u56FE\u7247\u8D8A\u591A\u8D8A\u5BB9\u6613\u89E6\u53D1 API \u56FE\u7247\u5904\u7406\u9519\u8BEF\u5E76\u62D6\u6162/\u6D88\u8017\u989D\u5EA6\uFF0C\u5EFA\u8BAE\u7528 /clear \u91CD\u5F00\u4E00\u4E2A\u5E72\u51C0\u4F1A\u8BDD\uFF0C\u6216\u51CF\u5C11\u540E\u7EED\u622A\u56FE\u3002`})))}_checkDeathLoop(i,n){if(this._loopTripped)return;let t=!1;try{const e=n||JSON.stringify(i);if(LOOP_POISON_PHRASES.some((s=>e.includes(s)))){const s=i.type==="assistant",u=e.includes('"type":"image"'),f=e.length<=POISON_MAX_NOTICE_LEN;t=!s&&(u||f)}}catch{}if(t&&(this._loopPoisonHits++,this._loopPoisonHits>=LOOP_MAX_POISON_HITS)){this._tripLoopBreaker("\u8BE5\u56FE\u7247/\u5185\u5BB9 API \u53CD\u590D\u65E0\u6CD5\u5904\u7406\u5E76\u5DF2\u88AB\u79FB\u9664\uFF0C\u8BF7\u4E0D\u8981\u518D\u7528 Read \u91CD\u65B0\u8BFB\u53D6\u5B83\u2014\u2014\u5B83\u5DF2\u4E0D\u53EF\u7528\u3002\u8BF7\u57FA\u4E8E\u73B0\u6709\u6587\u5B57\u4FE1\u606F\u7EE7\u7EED\uFF1B\u82E5\u786E\u5B9E\u9700\u8981\u8BE5\u56FE\uFF0C\u8BF7\u63D0\u793A\u7528\u6237\u91CD\u65B0\u4E0A\u4F20\u4E00\u5F20\u66F4\u5C0F\u7684\u622A\u56FE\u3002");return}if(i.type==="assistant"&&Array.isArray(i.message?.content)){const e=!!i.parent_tool_use_id,s=i.parent_tool_use_id||"main";for(const u of i.message.content){if(u.type!=="tool_use")continue;if(!e&&(this._loopTurnToolCalls++,this._loopTurnToolCalls>LOOP_MAX_TURN_TOOLCALLS)){this._tripLoopBreaker(`\u672C\u8F6E\u5DE5\u5177\u8C03\u7528\u5DF2\u8FBE ${this._loopTurnToolCalls} \u6B21\u5E76\u63D2\u5165\u68C0\u67E5\u70B9\u3002\u82E5\u4ECD\u5728\u6B63\u5E38\u63A8\u8FDB\uFF0C\u8BF7\u6982\u8FF0\u5F53\u524D\u8FDB\u5C55\u540E\u7EE7\u7EED\uFF1B\u82E5\u5728\u91CD\u590D\u540C\u7C7B\u64CD\u4F5C\u800C\u6CA1\u6709\u8FDB\u5C55\uFF0C\u8BF7\u6362\u4E00\u79CD\u601D\u8DEF\uFF0C\u6216\u5148\u5411\u7528\u6237\u6C47\u62A5\u518D\u7B49\u5F85\u6307\u793A\u3002`);return}const f=`${s}:${u.name}:${this._hashInput(u.input)}`,l=(this._loopSigCounts.get(f)||0)+1;if(this._loopSigCounts.set(f,l),l>=LOOP_MAX_IDENTICAL_CALLS){this._tripLoopBreaker(`\u5DE5\u5177\u300C${u.name}\u300D\u5DF2\u7528\u5B8C\u5168\u76F8\u540C\u7684\u53C2\u6570\u8C03\u7528 ${l} \u6B21\uFF0C\u7591\u4F3C\u9677\u5165\u6B7B\u5FAA\u73AF\u3002\u8BF7\u505C\u6B62\u91CD\u590D\u8BE5\u8C03\u7528\uFF0C\u6539\u7528\u4E0D\u540C\u53C2\u6570/\u4E0D\u540C\u5DE5\u5177\uFF0C\u6216\u8DF3\u8FC7\u8FD9\u4E00\u6B65\u7EE7\u7EED\u3002`);return}}}}_hashInput(i){let n;try{n=JSON.stringify(stripHeavyPayload(i))}catch{n=String(i)}n.length>4096&&(n=n.slice(0,4096));let t=5381;for(let e=0;e<n.length;e++)t=(t<<5)+t+n.charCodeAt(e)|0;return t.toString(36)}_tripLoopBreaker(i){if(this._loopTripped=!0,console.warn("[agent] \u{1F50C} \u6B7B\u5FAA\u73AF\u7194\u65AD:",i),this._loopAutoRecover>=LOOP_MAX_AUTO_RECOVER){this._pendingSteer=null,this.emit("agent:message",{type:"system",subtype:"warning",message:"\u26A0\uFE0F \u591A\u6B21\u81EA\u52A8\u7EA0\u504F\u4ECD\u672A\u8DF3\u51FA\u5FAA\u73AF\uFF0C\u5DF2\u505C\u6B62\u4EE5\u4FDD\u62A4 session \u989D\u5EA6\u3002\u8BF7 /clear \u91CD\u5F00\u6216\u6362\u4E2A\u95EE\u6CD5\u3002"}),this.interrupt();return}this._loopAutoRecover++,this._pendingSteer=i,this.emit("agent:message",{type:"system",subtype:"warning",message:`\u26A0\uFE0F \u7194\u65AD\u4FDD\u62A4\uFF08\u7B2C ${this._loopAutoRecover} \u6B21\u81EA\u52A8\u7EA0\u504F\uFF09\uFF1A${i}`}),this.interrupt()}_flushPendingSteer(){if(!this._pendingSteer)return;const i=this._pendingSteer;this._pendingSteer=null,setTimeout((()=>{!this._busy&&this.alive&&this.query(i,{internal:!0}).catch((()=>{}))}),600)}setFollowUp({enabled:i,intervalMinutes:n}={}){if(typeof i=="boolean"&&(this._followEnabled=i),n!=null){const t=Math.max(1,Math.min(180,Number(n)||15));this._followIntervalMs=Math.round(t*60*1e3)}return this._followEnabled?this._busy||this._maybeScheduleFollowUp():(this._cancelFollowUp(),this._followCount=0),this.emit("agent:message",{type:"system",subtype:"info",message:this._followEnabled?`\u{1F504} \u81EA\u52A8\u8DDF\u8FDB\u5DF2\u5F00\u542F\uFF1A\u6BCF ${Math.round(this._followIntervalMs/6e4)} \u5206\u949F\u81EA\u52A8\u67E5\u4E00\u6B21\u8FDB\u5EA6\u5E76\u6C47\u62A5\uFF08\u6700\u591A ${this._followMax} \u6B21\uFF1BAI \u5224\u65AD\u5168\u90E8\u5B8C\u6210\u4F1A\u81EA\u52A8\u505C\uFF09\u3002`:"\u{1F504} \u81EA\u52A8\u8DDF\u8FDB\u5DF2\u5173\u95ED\u3002"}),this.followUpState()}followUpState(){return{enabled:this._followEnabled,intervalMinutes:Math.round(this._followIntervalMs/6e4),max:this._followMax,count:this._followCount}}_cancelFollowUp(){this._followTimer&&(clearTimeout(this._followTimer),this._followTimer=null)}_cancelRelay(){this._relayTimer&&(clearTimeout(this._relayTimer),this._relayTimer=null)}_maybeRelayDraft(){!this.alive||this._relayTimer||(this._relayTimer=setTimeout((()=>{if(this._relayTimer=null,this._busy||!this.alive)return;let i=null;try{i=nextAutoSendDraft(this.id)}catch{return}if(!i)return;try{removeDraft(i.id)}catch{}const n=buildDraftPrompt(i);n.trim()&&(this.emit("agent:message",{type:"system",subtype:"info",message:"\u{1F4E5} \u81EA\u52A8\u63A5\u529B\uFF1A\u4E0A\u4E00\u8F6E\u5DF2\u5B8C\u6210\uFF0C\u53D1\u51FA\u4E0B\u9762\u8FD9\u6761\u8349\u7A3F"}),this.emit("agent:message",{type:"user",content:draftDisplayText(i)||n,timestamp:Date.now()}),this.emit("draft-relayed",{id:i.id,sessionId:this.id}),this.lastInputTime=Date.now(),this.query(n).catch((()=>{})))}),RELAY_DELAY_MS),this._relayTimer.unref&&this._relayTimer.unref())}_maybeScheduleFollowUp(){if(this._cancelFollowUp(),!(!this._followEnabled||!this.alive)){if(this._followStopSignal){this._followStopSignal=!1,this._followCount=0,this.emit("agent:message",{type:"system",subtype:"info",message:"\u{1F504} AI \u5DF2\u786E\u8BA4\u4EFB\u52A1\u5168\u90E8\u5B8C\u6210\uFF0C\u81EA\u52A8\u8DDF\u8FDB\u505C\u6B62\u3002"});return}if(this._followCount>=this._followMax){this.emit("agent:message",{type:"system",subtype:"info",message:`\u{1F504} \u81EA\u52A8\u8DDF\u8FDB\u5DF2\u8FDE\u7EED ${this._followMax} \u6B21\uFF0C\u6682\u505C\uFF08\u9632\u7A7A\u8F6C\u70E7\u989D\u5EA6\uFF09\u3002\u9700\u8981\u7EE7\u7EED\u53EF\u624B\u52A8\u95EE\u4E00\u53E5\u6216\u91CD\u5F00\u3002`});return}this._followTimer=setTimeout((()=>{this._followTimer=null,!(this._busy||!this.alive||!this._followEnabled)&&(this._followCount++,this.emit("agent:message",{type:"system",subtype:"info",message:`\u{1F504} \u81EA\u52A8\u8DDF\u8FDB\uFF08\u7B2C ${this._followCount}/${this._followMax} \u6B21\uFF09\uFF1A\u8BA9 AI \u67E5\u770B\u8FDB\u5EA6\u2026`}),this.query(FOLLOW_UP_PROMPT,{internal:!0}).catch((()=>{})))}),this._followIntervalMs)}}_startStallWatchdog(){this._stopStallWatchdog(),this._watchdogTimer=setInterval((()=>{if(!this._busy){this._stopStallWatchdog();return}if(this._awaitingTool)return;const i=Date.now()-this._lastActivityAt;if(i>=STALL_WATCHDOG_MS){const n=Math.round(i/1e3);console.warn(`[agent] \u23F1 \u505C\u6446\u770B\u95E8\u72D7\u89E6\u53D1\uFF1A\u7B49\u5F85\u6A21\u578B\u54CD\u5E94\u5DF2 ${n}s \u65E0\u4EFB\u4F55\u6D88\u606F\uFF0C\u5F3A\u5236\u4E2D\u65AD`),this.emit("agent:message",{type:"system",subtype:"warning",message:`\u23F1 \u68C0\u6D4B\u5230\u4F1A\u8BDD\u505C\u6446\uFF08\u7B49\u5F85\u6A21\u578B\u54CD\u5E94 ${n}s \u65E0\u54CD\u5E94\uFF0C\u7591\u4F3C API \u4F20\u8F93\u5C42\u91CD\u8BD5\u5361\u4F4F\uFF09\uFF0C\u5DF2\u5F3A\u5236\u4E2D\u65AD\u672C\u56DE\u5408\u3002\u8BF7\u91CD\u8BD5\u6216\u7A0D\u540E\u518D\u8BD5\u3002`}),this._stopStallWatchdog(),this.interrupt()}}),STALL_CHECK_INTERVAL_MS),this._watchdogTimer.unref&&this._watchdogTimer.unref()}_stopStallWatchdog(){this._watchdogTimer&&(clearInterval(this._watchdogTimer),this._watchdogTimer=null)}_onControlRequest(i){const n=i.request||{},t=i.request_id;if(n.subtype!=="can_use_tool"){this._writeStdin({type:"control_response",response:{subtype:"error",request_id:t,error:`myhi \u4E0D\u652F\u6301 ${n.subtype}`}});return}if(n.tool_name==="AskUserQuestion"||n.tool_name==="ExitPlanMode")return this._openInteraction({id:t,kind:n.tool_name==="AskUserQuestion"?"ask":"plan",input:n.input||{},toolUseId:n.tool_use_id});this._ctlReply(t,{behavior:"deny",message:"\u5F53\u524D\u6743\u9650\u6A21\u5F0F\u4E0D\u5141\u8BB8\u6B64\u64CD\u4F5C\uFF08myhi \u65E0\u4EBA\u503C\u5B88\uFF0C\u65E0\u6CD5\u9010\u9879\u6388\u6743\uFF09\u3002\u8BF7\u57FA\u4E8E\u73B0\u72B6\u7EE7\u7EED\uFF0C\u6216\u5728\u56DE\u590D\u91CC\u8BF4\u660E\u9700\u8981\u7528\u6237\u5207\u6362\u5230\u81EA\u52A8\u6267\u884C\u3002"})}_ctlReply(i,n){return this._writeStdin({type:"control_response",response:{subtype:"success",request_id:i,response:n}})}get pendingInteractions(){return[...this._interactions?.values()||[]].map((i=>i.view))}_openInteraction(i){this._interactions||(this._interactions=new Map);const n=redactDeep(this._pseudo?.enabled?redactDeep(i.input,this._pseudo.restore):i.input,this._redactor);i.view={id:i.id,kind:i.kind,toolUseId:i.toolUseId,at:Date.now(),questions:i.kind==="ask"?n.questions||[]:void 0,plan:i.kind==="plan"?String(n.plan||""):void 0};const t=this._followEnabled?INTERACTION_WAIT_FOLLOW_MS:INTERACTION_WAIT_MS;i.view.deadline=Date.now()+t,i.timer=setTimeout((()=>this.respondInteraction(i.id,{skip:!0,timeout:!0},"\u7CFB\u7EDF")),t),i.timer.unref&&i.timer.unref(),this._interactions.set(i.id,i),this.emit("agent:interaction",i.view)}respondInteraction(i,n={},t=""){const e=this._interactions?.get(i);if(!e)return{ok:!1,error:"\u8FD9\u4E2A\u63D0\u95EE\u5DF2\u7ECF\u5904\u7406\u8FC7\u4E86"};clearTimeout(e.timer),this._interactions.delete(i);const s=f=>this._pseudo?.enabled?this._pseudo.pseudonymize(String(f)).text:String(f);let u;if(e.kind==="ask")if(n.skip||!n.answers||!Object.keys(n.answers).length)this._ctlReply(i,{behavior:"deny",message:n.timeout?"\u7528\u6237\u8F83\u957F\u65F6\u95F4\u6CA1\u6709\u4F5C\u7B54\u3002\u8BF7\u6309\u4F60\u7684\u6700\u4F73\u5224\u65AD\u7EE7\u7EED\uFF0C\u5E76\u5728\u56DE\u590D\u91CC\u8BF4\u660E\u4F60\u505A\u4E86\u54EA\u4E9B\u5047\u8BBE\u3002":"\u7528\u6237\u9009\u62E9\u4E0D\u56DE\u7B54\u8FD9\u4E2A\u95EE\u9898\u3002\u8BF7\u6309\u4F60\u7684\u6700\u4F73\u5224\u65AD\u7EE7\u7EED\uFF0C\u5E76\u5728\u56DE\u590D\u91CC\u8BF4\u660E\u4F60\u505A\u4E86\u54EA\u4E9B\u5047\u8BBE\u3002"}),u=n.timeout?"\u23ED \u63D0\u95EE\u7B49\u5F85\u8D85\u65F6\uFF0CAI \u5C06\u6309\u6700\u4F73\u5224\u65AD\u7EE7\u7EED":`\u23ED ${t} \u8DF3\u8FC7\u4E86\u63D0\u95EE\uFF0CAI \u5C06\u6309\u6700\u4F73\u5224\u65AD\u7EE7\u7EED`;else{const f={},l=e.input.questions||[],o=e.view.questions||[];o.forEach(((c,r)=>{const a=n.answers[c.question];a!==void 0&&l[r]&&(f[l[r].question]=s(a))})),this._ctlReply(i,{behavior:"allow",updatedInput:{...e.input,answers:f}}),u=`\u{1F4DD} ${t} \u5DF2\u56DE\u7B54\uFF1A`+o.map((c=>`${c.header||c.question}\uFF1D${n.answers[c.question]??"\uFF08\u672A\u7B54\uFF09"}`)).join("\uFF1B")}else if(n.approve)this._ctlReply(i,{behavior:"allow",updatedInput:e.input,updatedPermissions:[{type:"setMode",mode:"bypassPermissions",destination:"session"}]}),u=`\u2705 ${t} \u6279\u51C6\u4E86\u65B9\u6848\uFF0CAI \u5F00\u59CB\u6267\u884C`;else{const f=String(n.feedback||"").trim();this._ctlReply(i,{behavior:"deny",message:n.timeout?"\u7528\u6237\u8F83\u957F\u65F6\u95F4\u6CA1\u6709\u5BA1\u6279\u65B9\u6848\uFF0C\u6682\u4E0D\u6267\u884C\u3002\u4FDD\u6301\u8BA1\u5212\u6A21\u5F0F\uFF0C\u7B49\u5F85\u7528\u6237\u56DE\u590D\u3002":`\u7528\u6237\u5E0C\u671B\u4FEE\u6539\u65B9\u6848${f?"\uFF1A"+s(f):""}\u3002\u8BF7\u6309\u610F\u89C1\u4FEE\u6539\u540E\u91CD\u65B0\u7528 ExitPlanMode \u63D0\u4EA4\u3002`}),u=n.timeout?"\u23ED \u65B9\u6848\u5BA1\u6279\u7B49\u5F85\u8D85\u65F6\uFF0C\u6682\u4E0D\u6267\u884C":`\u270F\uFE0F ${t} \u8981\u6C42\u4FEE\u6539\u65B9\u6848${f?"\uFF1A"+f:""}`}return this.emit("agent:interaction-closed",{id:i,kind:e.kind}),this.emit("agent:message",{type:"system",subtype:"info",message:u}),{ok:!0}}_dropInteractions(){if(this._interactions?.size){for(const i of this._interactions.values())clearTimeout(i.timer),this.emit("agent:interaction-closed",{id:i.id,kind:i.kind});this._interactions.clear()}}_hardKillTree(i){if(i)try{if(process.platform==="win32")(0,external_child_process_namespaceObject.execSync)(`taskkill /PID ${i} /F /T`,{stdio:"pipe",timeout:5e3});else{try{process.kill(i,"SIGTERM")}catch{}setTimeout((()=>{try{process.kill(i,0)}catch{return}try{process.kill(i,"SIGKILL")}catch{}}),1e3)}}catch{}}get canInject(){return!!this._injectable&&!!this._proc&&this._busy}inject(i,{display:n}={}){if(!this._injectable)return{ok:!1,error:"\u5F53\u524D Claude \u7248\u672C\u4E0D\u652F\u6301\u63D2\u8BDD\uFF0C\u8BF7\u5347\u7EA7 Claude Code \u540E\u91CD\u8BD5"};if(!this._proc||!this._busy)return{ok:!1,error:"AI \u73B0\u5728\u6CA1\u5728\u5E72\u6D3B\uFF0C\u76F4\u63A5\u53D1\u9001\u5C31\u884C"};if(this._interactions?.size)return{ok:!1,error:"AI \u6B63\u5728\u7B49\u4F60\u56DE\u7B54\u63D0\u95EE / \u5BA1\u6279\u65B9\u6848\uFF0C\u8BF7\u5148\u5728\u5F39\u7A97\u91CC\u5904\u7406"};if(i=typeof i=="string"?i.trim():"",!i)return{ok:!1,error:"\u63D2\u8BDD\u5185\u5BB9\u662F\u7A7A\u7684"};if(i.startsWith("/"))return{ok:!1,error:"\u63D2\u8BDD\u4E0D\u652F\u6301 / \u547D\u4EE4\uFF0C\u8BF7\u7B49 AI \u5E72\u5B8C\u518D\u53D1"};let t=i;if(this._pseudo?.enabled){const l=this._pseudo.pseudonymize(i);t=l.text;const o=this.claudeSessionId||this.id;saveMap(o,this._pseudoMap),l.count>0&&appendAudit(o,{ts:Date.now(),level:this._pseudo.level,maskedCount:l.count,byType:l.byType,sentToModel:l.text,inject:!0})}const e=(0,external_crypto_.randomUUID)();if(!this._writeStdin({type:"user",uuid:e,message:{role:"user",content:t}}))return{ok:!1,error:"Claude \u8FDB\u7A0B\u4E0D\u53EF\u5199\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5"};this._injected||(this._injected=new Map);const s=Date.now(),u=redactDeep(n||i,this._redactor),f={type:"user",content:u,timestamp:s,inject:{id:e,state:"pending"}};return this._injected.set(e,f),this._history.push(f),this.emit("agent:message",{type:"user",content:u,timestamp:s,inject:{id:e,state:"pending"}}),this.lastInputTime=s,{ok:!0,id:e}}_onReplay(i){const n=i.uuid&&this._injected?.get(i.uuid);n&&(this._injected.delete(i.uuid),n.inject.state="seen",this.emit("agent:message",{type:"system",subtype:"inject_state",id:i.uuid,state:"seen"}),this._injected.size||clearTimeout(this._injectWaitTimer)),this._busy||(this._busy=!0,this._interrupted=!1,this.emit("agent:busy",!0),this._lastActivityAt=Date.now(),this._awaitingTool=!1,this._startStallWatchdog())}refreshSkills(){if(!this._proc)return!1;if(this._busy)return this._skillsDirty=!0,!0;this._skillsDirty=!1,this._expectExit=!0;const i=this._proc.pid;return this._proc=null,this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._hardKillTree(i),this.emit("agent:message",{type:"system",subtype:"info",message:"\u{1F9E0} \u6280\u80FD\u6709\u53D8\u5316\uFF1A\u4E0B\u4E00\u8F6E AI \u4F1A\u91CD\u65B0\u52A0\u8F7D\u6280\u80FD\uFF08\u63A5\u7740\u539F\u6765\u7684\u5BF9\u8BDD\uFF09"}),!0}_dropInjected(i){if(clearTimeout(this._injectWaitTimer),!!this._injected?.size){for(const[n,t]of this._injected)t.inject.state="dropped",this.emit("agent:message",{type:"system",subtype:"inject_state",id:n,state:"dropped",reason:i});this._injected.clear()}}interrupt(){if(this._dropInteractions(),this._describing){this._describeAborted=!0,this._describing.abort();return}if(!this._proc||!this._busy)return;this._interrupted=!0;const i=this._proc.pid,n=this._proc,t=Date.now();this._injected?.size&&this.emit("agent:message",{type:"system",subtype:"info",message:"\u26A1 \u4F60\u521A\u63D2\u7684\u8BDD\u5DF2\u7ECF\u6392\u8FDB AI \u7684\u961F\u5217\uFF0C\u4E2D\u65AD\u540E\u5B83\u4F1A\u63A5\u7740\u5904\u7406\uFF1B\u4E0D\u9700\u8981\u7684\u8BDD\u7B49\u5B83\u5F00\u59CB\u540E\u518D\u70B9\u4E00\u6B21\u505C\u6B62"});const s=this._writeStdin({type:"control_request",request_id:`interrupt-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,request:{subtype:"interrupt"}})?1500:0;setTimeout((()=>{this._busy&&this._proc===n&&((this._lastResultAt||0)>=t||(console.log(`[agent] graceful interrupt \u8D85\u65F6\uFF0C\u5F3A\u5236\u7ED3\u675F\u8FDB\u7A0B\u6811 PID ${i}`),this._hardKillTree(i)))}),s),this.emit("agent:message",{type:"system",subtype:"interrupted",message:"\u67E5\u8BE2\u5DF2\u4E2D\u65AD"})}kill(){if(this._dropInteractions(),this._dropInjected("\u4F1A\u8BDD\u5DF2\u7EC8\u6B62"),this.alive=!1,this._cancelRelay(),this._cancelFollowUp(),this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._proc&&(this._hardKillTree(this._proc.pid),this._proc=null),this._pendingReject){try{this._pendingReject(new Error("\u4F1A\u8BDD\u5DF2\u7EC8\u6B62"))}catch{}this._pendingResolve=null,this._pendingReject=null}this._busy=!1}_readTranscriptCtx(){if(!this.claudeSessionId)return null;try{const i=(0,external_path_.join)((0,external_os_.homedir)(),".claude","projects");if(!(0,external_fs_.existsSync)(i))return null;for(const n of(0,external_fs_.readdirSync)(i,{withFileTypes:!0})){if(!n.isDirectory())continue;const t=(0,external_path_.join)(i,n.name,this.claudeSessionId+".jsonl");if(!(0,external_fs_.existsSync)(t))continue;const e=(0,external_fs_.statSync)(t).size,s=Math.min(e,65536),u=Buffer.alloc(s),f=(0,external_fs_.openSync)(t,"r");try{(0,external_fs_.readSync)(f,u,0,s,e-s)}finally{(0,external_fs_.closeSync)(f)}const l=u.toString("utf8").split(`
|
|
401
401
|
`).filter(Boolean);for(let o=l.length-1;o>=0;o--)try{const c=JSON.parse(l[o]),r=c.type==="assistant"?c.message?.usage:null;if(r&&(r.input_tokens||0)+(r.cache_read_input_tokens||0)+(r.cache_creation_input_tokens||0)>0)return r}catch{}}}catch{}return null}_loadResumedHistory(){try{const i=(0,external_path_.join)((0,external_os_.homedir)(),".claude","projects");if(!(0,external_fs_.existsSync)(i))return;for(const n of(0,external_fs_.readdirSync)(i,{withFileTypes:!0})){if(!n.isDirectory())continue;const t=(0,external_path_.join)(i,n.name,this.claudeSessionId+".jsonl");if(!(0,external_fs_.existsSync)(t))continue;const e=(0,external_fs_.readFileSync)(t,"utf8").split(`
|
|
402
402
|
`).filter(Boolean),s=e.slice(-200);if(!this.firstUserText)for(const u of e.slice(0,40))try{const f=JSON.parse(u);if(f.type!=="user"&&f.type!=="human")continue;const l=f.message?.content,o=(typeof l=="string"?l:l?.find?.((c=>c.type==="text"))?.text||"").trim();if(!o||o.startsWith("/")||/^(Caveat:|<command-name>|<system-reminder>|<local-command|<task-notification>)/.test(o))continue;this.firstUserText=o.slice(0,160);break}catch{}for(const u of s)try{const f=JSON.parse(u);if(f.isSidechain)continue;if(f.type==="human"||f.type==="user"&&f.message?.content){const l=typeof f.message.content=="string"?f.message.content:f.message.content.find((o=>o.type==="text"))?.text||"";l&&this._history.push({type:"user",content:l,timestamp:f.timestamp})}else if(f.type==="assistant"&&f.message?.content){this._history.push({type:"assistant",message:f.message,timestamp:f.timestamp});const l=f.message.usage;if(l){const o=(l.input_tokens||0)+(l.cache_read_input_tokens||0)+(l.cache_creation_input_tokens||0);this._contextTokens=o}}else f.type==="result"&&this._history.push({type:"result",total_cost_usd:f.costUSD||f.total_cost_usd,timestamp:f.timestamp})}catch{}try{const u=(0,external_fs_.statSync)(t).mtimeMs;u>0&&(this._lastActivityAt=Math.max(this._lastActivityAt,u))}catch{}return}}catch(i){console.warn("[agent] \u52A0\u8F7D\u6062\u590D\u4F1A\u8BDD\u5386\u53F2\u5931\u8D25:",i.message)}}get isBusy(){return this._busy}getRecentHistory(i=20){return this._history.slice(-i)}getUsage(){return{...this._usage}}addViewer(i,n){this._viewers.add(i),n&&this._viewerNames.set(i,n)}removeViewer(i){this._viewers.delete(i),this._viewerNames.delete(i)}get viewerCount(){return new Set(this._viewerNames.values()).size||this._viewers.size}takeControl(i,n){this.controlHolder=i,this.controlHolderName=n||null,this.lastInputTime=Date.now()}releaseControl(){this.controlHolder=null,this.controlHolderName=null,this.lastInputTime=null}isController(i){return this.controlHolder===i}setPermissionMode(i){this.permissionMode=normalizePermissionMode(i),this._proc&&(this._expectExit=!0,this.kill(),this.alive=!0)}reset(){this._dropInteractions(),this._dropInjected("\u5DF2\u5F00\u59CB\u65B0\u5BF9\u8BDD"),this._proc&&(this._expectExit=!0,this._hardKillTree(this._proc.pid),this._proc=null),this.claudeSessionId=null,this._history=[],this._contextTokens=0,this._buffer="",this._imageBlockCount=0,this._imageNudgeAt=IMAGE_NUDGE_STEP,this._cancelFollowUp(),this._followCount=0,this._followStopSignal=!1,this._cancelRelay(),this.permissionMode="bypassPermissions"}_lastAssistantText(){for(let i=this._history.length-1,n=0;i>=0&&n<80;i--,n++){const t=this._history[i];if(t?.type!=="assistant"||t.parent_tool_use_id)continue;const s=(t.message?.content||[]).filter((u=>u?.type==="text")).map((u=>u.text)).join(" ").replace(/[#*`>|_~\-]+/g," ").replace(/\s+/g," ").trim();if(s)return s.slice(0,80)}return""}toJSON(){return{id:this.id,title:this.title,firstUserText:this.firstUserText||"",cwd:this.cwd,tags:this.tags,createdAt:this.createdAt,lastActivityAt:this._lastActivityAt||null,mode:"agent",alive:this.alive,viewers:this.viewerCount,controlHolder:this.controlHolder,controlHolderName:this.controlHolderName,permissionMode:this.permissionMode,modelId:this.modelId||null,effectiveModel:this._currentModel(),planModel:sceneModel("plan")||null,owner:this.owner,claudeSessionId:this.claudeSessionId,busy:this._busy,pending:this._interactions?.size||0,lastText:this._lastAssistantText(),interactive:!!this._interactive,injectable:_replayCap,usage:this._usage,contextTokens:this._contextTokens,followUp:this.followUpState()}}}function getSessionHealth(d){const i={found:!1,persistedMode:null,poisoned:!1,messageCount:0,transcriptKB:0,imageCount:0,updatedAt:null};if(!d)return i;try{const n=(0,external_path_.join)((0,external_os_.homedir)(),".claude","projects");if(!(0,external_fs_.existsSync)(n))return i;for(const t of(0,external_fs_.readdirSync)(n,{withFileTypes:!0})){if(!t.isDirectory())continue;const e=(0,external_path_.join)(n,t.name,d+".jsonl");if(!(0,external_fs_.existsSync)(e))continue;const s=(0,external_fs_.readFileSync)(e,"utf8"),u=s.split(`
|
|
403
403
|
`).filter(Boolean);let f=null,l=null,o=0;for(const c of u){const r=c.match(/"type":"image"/g);if(r&&(o+=r.length),c.includes("permissionMode"))try{const a=JSON.parse(c);a.type==="user"&&a.permissionMode&&(f=a.permissionMode)}catch{}}try{const c=JSON.parse(u[u.length-1]);c.timestamp&&(l=c.timestamp)}catch{}return{found:!0,persistedMode:f,poisoned:!!(f&&f!=="bypassPermissions"),messageCount:u.length,transcriptKB:Math.round(s.length/1024),imageCount:o,updatedAt:l}}}catch{}return i}let _claudeSessionsCache=null,_claudeSessionsCacheTime=0;const CLAUDE_SESSIONS_CACHE_TTL=3e4;function listLocalClaudeSessions(d){const i=Date.now();if(_claudeSessionsCache&&i-_claudeSessionsCacheTime<CLAUDE_SESSIONS_CACHE_TTL){if(!d)return _claudeSessionsCache;const s=(0,external_path_.resolve)((0,external_path_.normalize)(d)).replace(/[\\/]+$/,"");return _claudeSessionsCache.filter((u=>(0,external_path_.resolve)((0,external_path_.normalize)(u.projectPath)).replace(/[\\/]+$/,"").startsWith(s)))}const n=[],t=d?(0,external_path_.resolve)((0,external_path_.normalize)(d)).replace(/[\\/]+$/,""):null;try{const s=(0,external_path_.join)((0,external_os_.homedir)(),".claude","projects");if(!(0,external_fs_.existsSync)(s))return n;for(const u of(0,external_fs_.readdirSync)(s,{withFileTypes:!0})){if(!u.isDirectory())continue;const f=(0,external_path_.join)(s,u.name);try{for(const l of(0,external_fs_.readdirSync)(f)){if(!l.endsWith(".jsonl"))continue;const o=l.replace(".jsonl",""),c=(0,external_path_.join)(f,l);try{const r=(0,external_fs_.readFileSync)(c,"utf8").split(`
|
|
@@ -436,7 +436,7 @@ description:
|
|
|
436
436
|
`)+`
|
|
437
437
|
`:d}async function importPack(d,i){const n=await readManifest(d),t=(0,external_path_.resolve)(i);(0,external_fs_.mkdirSync)(t,{recursive:!0});const e=n.conv?.sid||null,s=(0,external_path_.join)(claudeProjectsDir(),encodeCwd(t)),u=e?findTranscriptPath(e)?(0,external_crypto_.randomUUID)():e:null;let f=null,l=null,o=null;const c=[];await readTar(d,(async({name:h,mode:m})=>{if(h==="myhi-pack.json")return null;if(h.startsWith("files/")){const p=safeJoin(t,h.slice(6));return p?fileSink(p,m&493|384):null}if(h==="myhi/guard.json")return memSink((p=>{try{o=JSON.parse(p.toString("utf8"))}catch{}}));if(h.startsWith("claude/memory/")){const p=h.slice(14);return memSink((v=>c.push({rel:p,buf:v})))}if(!e)return null;if(h===`claude/${e}.jsonl`)return memSink((p=>{f=p.toString("utf8")}));if(h.startsWith(`claude/${e}/`)){const p=safeJoin((0,external_path_.join)(s,u),h.slice(`claude/${e}/`.length));return p?fileSink(p):null}return h==="myhi/pseudo-map.json"?memSink((p=>{try{l=JSON.parse(p.toString("utf8"))}catch{}})):null})),o&&importGuardBag(t,o);const r={written:0,kept:0};if(c.length){const h=(0,external_path_.join)(s,"memory"),m=[[n.memory?.claudeDir||n.conv?.claudeDir,s],[n.cwd,t],[n.home,(0,external_os_.homedir)()]];for(const p of c){const v=safeJoin(h,p.rel);if(!v)continue;const g=rewritePaths(p.buf.toString("utf8"),m);(0,external_fs_.mkdirSync)((0,external_path_.dirname)(v),{recursive:!0}),(0,external_fs_.existsSync)(v)?p.rel==="MEMORY.md"?(0,external_fs_.writeFileSync)(v,mergeMemoryIndex((0,external_fs_.readFileSync)(v,"utf8"),g)):r.kept++:((0,external_fs_.writeFileSync)(v,g),r.written++)}}let a=null;if(f&&u){(0,external_fs_.mkdirSync)(s,{recursive:!0});const h=n.conv?.claudeDir?[[n.conv.claudeDir,s]]:[],m=n.home?[[n.home,(0,external_os_.homedir)()]]:[];(0,external_fs_.writeFileSync)((0,external_path_.join)(s,u+".jsonl"),rewriteTranscript(f,n.cwd||"",t,e,u,h,m),{mode:384}),l&&saveMap(u,l),a=u}return{manifest:n,sid:a,memory:r}}const ZIP_SKIP_DIRS=new Set([".git","node_modules",".venv","venv","__pycache__"]),ZIP_MAX_BYTES=4*1024**3-64*1024**2,ZIP_MAX_FILES=65e3,PACKED=/\.(zip|gz|tgz|7z|rar|xz|bz2|jpe?g|png|gif|webp|mp4|mov|avi|mkv|mp3|m4a|aac|pdf|docx|xlsx|pptx|myhipack)$/i,CRC_TABLE=(()=>{const d=new Uint32Array(256);for(let i=0;i<256;i++){let n=i;for(let t=0;t<8;t++)n=n&1?3988292384^n>>>1:n>>>1;d[i]=n>>>0}return d})();function crc32(d,i=0){i=~i>>>0;for(let n=0;n<d.length;n++)i=CRC_TABLE[(i^d[n])&255]^i>>>8;return~i>>>0}function dosTime(d){const i=new Date(d);return{time:i.getHours()<<11|i.getMinutes()<<5|Math.floor(i.getSeconds()/2),date:Math.max(1980,i.getFullYear())-1980<<9|i.getMonth()+1<<5|i.getDate()}}function collectZipFiles(d){const i=[],n=new Set;let t=0;const e=(u,f,l)=>{if(l>40||i.length>ZIP_MAX_FILES)return;let o;try{o=(0,external_fs_.readdirSync)(u,{withFileTypes:!0})}catch{return}for(const c of o){if(c.isSymbolicLink())continue;const r=(0,external_path_.join)(u,c.name);if(c.isDirectory()){if(ZIP_SKIP_DIRS.has(c.name)){n.add(c.name);continue}e(r,f+"/"+c.name,l+1)}else c.isFile()&&s(r,f+"/"+c.name)}},s=(u,f)=>{let l;try{l=(0,external_fs_.lstatSync)(u)}catch{return}i.push({abs:u,name:f,size:l.size,mtime:l.mtimeMs,mode:l.mode&511}),t+=l.size};for(const u of d){let f;try{f=(0,external_fs_.lstatSync)(u.abs)}catch{continue}f.isDirectory()?e(u.abs,u.name,0):f.isFile()&&s(u.abs,u.name)}return{files:i,bytes:t,skipped:[...n]}}async function zip_put(d,i){d.write(i)||await(0,external_events_.once)(d,"drain")}async function writeZip(d,i){const n=[];let t=0;for(const u of i){const f=Buffer.from(u.name,"utf8"),{time:l,date:o}=dosTime(u.mtime||Date.now()),c=Buffer.alloc(30);c.writeUInt32LE(67324752,0),c.writeUInt16LE(20,4),c.writeUInt16LE(2056,6),c.writeUInt16LE(8,8),c.writeUInt16LE(l,10),c.writeUInt16LE(o,12),c.writeUInt16LE(f.length,26),await zip_put(d,c),await zip_put(d,f);const r=t;t+=30+f.length;let a=0,h=0,m=0;const p=(0,external_zlib_.createDeflateRaw)({level:PACKED.test(u.name)?1:6}),v=(async()=>{try{for await(const _ of(0,external_fs_.createReadStream)(u.abs))a=crc32(_,a),h+=_.length,p.write(_)||await(0,external_events_.once)(p,"drain")}finally{p.end()}})();for await(const _ of p)m+=_.length,await zip_put(d,_);await v.catch((()=>{})),t+=m;const g=Buffer.alloc(16);g.writeUInt32LE(134695760,0),g.writeUInt32LE(a,4),g.writeUInt32LE(m,8),g.writeUInt32LE(h,12),await zip_put(d,g),t+=16,n.push({name:f,time:l,date:o,crc:a,csize:m,usize:h,start:r,mode:u.mode||420})}const e=t;for(const u of n){const f=Buffer.alloc(46);f.writeUInt32LE(33639248,0),f.writeUInt16LE(788,4),f.writeUInt16LE(20,6),f.writeUInt16LE(2056,8),f.writeUInt16LE(8,10),f.writeUInt16LE(u.time,12),f.writeUInt16LE(u.date,14),f.writeUInt32LE(u.crc,16),f.writeUInt32LE(u.csize,20),f.writeUInt32LE(u.usize,24),f.writeUInt16LE(u.name.length,28),f.writeUInt32LE((32768|u.mode)<<16>>>0,38),f.writeUInt32LE(u.start,42),await zip_put(d,f),await zip_put(d,u.name),t+=46+u.name.length}const s=Buffer.alloc(22);s.writeUInt32LE(101010256,0),s.writeUInt16LE(n.length,8),s.writeUInt16LE(n.length,10),s.writeUInt32LE(t-e,12),s.writeUInt32LE(e,16),await zip_put(d,s)}const REQUIRED_FILES=["package.json","bin/myhi.js","bin/daemon.js","dist/index.js","dist/lib","dist/login.html","dist/index.html","dist/chat.html","dist/admin.html","dist/grid.html","dist/terminal.html"];function checkInstall(d,i){const n=REQUIRED_FILES.filter((s=>!(0,external_fs_.existsSync)((0,external_path_.join)(d,s))));let t=null;try{t=JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(d,"package.json"),"utf8")).version}catch{}let e=null;return n.length?e=`\u5B89\u88C5\u4E0D\u5B8C\u6574\uFF0C\u7F3A\u5C11 ${n.join("\u3001")}\uFF08\u53EF\u80FD\u88AB\u6740\u6BD2\u8F6F\u4EF6\u62E6\u622A\u6216\u5B89\u88C5\u88AB\u4E2D\u65AD\uFF09`:i&&t!==i&&(e=`\u5B89\u88C5\u540E\u7248\u672C\u662F ${t||"\u672A\u77E5"}\uFF0C\u4E0D\u662F\u671F\u671B\u7684 ${i}\uFF08npm \u53EF\u80FD\u88C5\u5230\u4E86\u522B\u7684\u76EE\u5F55\u6216\u955C\u50CF\u672A\u540C\u6B65\uFF09`),{ok:!e,version:t,missing:n,error:e}}function upgradeStatusFile(d){return(0,external_path_.join)(d,"upgrade-status.json")}function globalPrefixOf(d){const i=(0,external_path_.resolve)(d),n=(0,external_path_.dirname)((0,external_path_.dirname)(i));return(0,external_path_.basename)((0,external_path_.dirname)(i))!=="@wendongfly"||(0,external_path_.basename)(n)!=="node_modules"?null:process.platform==="win32"?(0,external_path_.dirname)(n):(0,external_path_.basename)((0,external_path_.dirname)(n))==="lib"?(0,external_path_.dirname)((0,external_path_.dirname)(n)):null}function npmUpgradeCmd(d,i=REGISTRIES.official){const n=process.platform==="win32",t=(0,external_path_.join)((0,external_path_.dirname)(process.execPath),n?"npm.cmd":"npm"),e=(0,external_fs_.existsSync)(t)?`"${t}"`:n?"npm.cmd":"npm",s=globalPrefixOf(d);return`${e} install -g @wendongfly/myhi@latest --registry ${i}${s?` --prefix "${s}"`:""}`}const REGISTRIES={official:"https://registry.npmjs.org",mirror:"https://registry.npmmirror.com"},registryName=d=>d===REGISTRIES.official?"\u5B98\u65B9\u6E90":d===REGISTRIES.mirror?"\u56FD\u5185\u955C\u50CF":d;function registryOrder(d){return d==="official"?[REGISTRIES.official]:d==="mirror"?[REGISTRIES.mirror]:d&&/^https?:\/\//.test(d)?[String(d).replace(/\/+$/,"")]:[REGISTRIES.official,REGISTRIES.mirror]}async function fetchLatest(d,i,n=8e3){try{const t=await fetch(`${d}/${i}/latest`,{headers:{Accept:"application/json"},signal:AbortSignal.timeout(n)});return t.ok&&(await t.json()).version||null}catch{return null}}function versionGt(d,i){const n=String(d||"").split(/[.-]/).map(Number),t=String(i||"").split(/[.-]/).map(Number);for(let e=0;e<3;e++){const s=n[e]||0,u=t[e]||0;if(s!==u)return s>u}return!1}async function latestVersion(d,i){for(const n of registryOrder(i)){const t=await fetchLatest(n,d);if(t)return{version:t,registry:n}}return null}async function upgradeCandidates(d,i,n){const t=registryOrder(n),s=(await Promise.all(t.map((async l=>({registry:l,version:await fetchLatest(l,d)}))))).filter((l=>l.version)),u=s.filter((l=>!i||versionGt(l.version,i)));let f=null;return u.length||(s.length?f=`\u5DF2\u7ECF\u662F\u6700\u65B0\u7248\u672C ${i}`+(s.some((l=>l.registry!==REGISTRIES.official))&&!s.some((l=>l.registry===REGISTRIES.official))?"\uFF08\u5B98\u65B9\u6E90\u8FDE\u4E0D\u4E0A\uFF0C\u4EE5\u56FD\u5185\u955C\u50CF\u4E3A\u51C6\uFF1B\u955C\u50CF\u53EF\u80FD\u8FD8\u6CA1\u540C\u6B65\u5230\u6700\u65B0\uFF0C\u8FC7\u4E00\u4F1A\u513F\u518D\u8BD5\uFF09":""):f=`${t.map(registryName).join("\u548C")}${t.length>1?"\u90FD":""}\u8FDE\u4E0D\u4E0A\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\uFF08\u6216\u5728 \u8BBE\u7F6E \u203A \u670D\u52A1 \u203A \u5347\u7EA7\u4E0B\u8F7D\u6E90 \u6362\u4E00\u4E2A\uFF09`),{candidates:u,reachable:s,note:f}}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 d=(0,external_path_.join)(server_configDir,"cert.pem"),i=(0,external_path_.join)(server_configDir,"key.pem");if((0,external_fs_.existsSync)(d)&&(0,external_fs_.existsSync)(i))try{return{cert:(0,external_fs_.readFileSync)(d),key:(0,external_fs_.readFileSync)(i)}}catch{}try{const n=selfsigned.generate([{name:"commonName",value:"myhi"}],{days:3650,keySize:2048});return(0,external_fs_.writeFileSync)(d,n.cert,"utf8"),(0,external_fs_.writeFileSync)(i,n.private,"utf8"),console.log("[myhi] \u81EA\u7B7E\u540D HTTPS \u8BC1\u4E66\u5DF2\u751F\u6210"),{cert:n.cert,key:n.private}}catch{}try{return(0,external_child_process_namespaceObject.execSync)(`openssl req -x509 -newkey rsa:2048 -keyout "${i}" -out "${d}" -days 3650 -nodes -subj "/CN=myhi"`,{stdio:"pipe",timeout:1e4}),{cert:(0,external_fs_.readFileSync)(d),key:(0,external_fs_.readFileSync)(i)}}catch(n){return console.warn(`[myhi] \u751F\u6210 HTTPS \u8BC1\u4E66\u5931\u8D25: ${n.message?.split(`
|
|
438
438
|
`)[0]||n}`),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(d,i){let n=!1;try{process.kill(d,0),n=!0}catch{}if(!n)return!0;console.log(`[myhi] \u68C0\u6D4B\u5230\u5DF2\u8FD0\u884C\u7684${i} (PID ${d})\uFF0C\u6B63\u5728\u505C\u6B62...`);try{process.platform==="win32"?(0,external_child_process_namespaceObject.execSync)(`taskkill /PID ${d} /F /T`,{stdio:"pipe",timeout:5e3}):process.kill(d,"SIGTERM")}catch{}const t=Date.now()+5e3;for(;Date.now()<t;){try{process.kill(d,0)}catch{return!0}const s=Date.now()+200;for(;Date.now()<s;);}let e=!1;try{process.kill(d,0),e=!0}catch{}return!e}(function d(){try{const i=parseInt((0,external_fs_.readFileSync)(daemonPidFile,"utf8").trim(),10);if(i&&i!==process.pid&&i!==parseInt(process.env.MYHI_DAEMON_PID||"0",10)){let n=!1;try{process.kill(i,0),n=!0}catch{}if(n&&!IS_DAEMON_CHILD){console.log("[myhi] \u68C0\u6D4B\u5230\u540E\u53F0 daemon \u5728\u8FD0\u884C\uFF0C\u5148\u505C\u6B62..."),killOldProcess(i,"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 i=parseInt((0,external_fs_.readFileSync)(pidFile,"utf8").trim(),10);i&&i!==process.pid&&(killOldProcess(i,"\u5B9E\u4F8B")||(console.error(`[myhi] \u65E0\u6CD5\u505C\u6B62\u65E7\u8FDB\u7A0B (PID ${i})\uFF0C\u8BF7\u624B\u52A8\u6267\u884C\uFF1A`),console.error(" myhi stop"),console.error(` \u6216: ${process.platform==="win32"?`taskkill /PID ${i} /F`:`kill -9 ${i}`}`),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 d of manager.listSessions())try{d.kill()}catch{}}}catch{}cleanupPid()}process.on("exit",cleanupPid),process.on("SIGTERM",(()=>{gracefulShutdown(),process.exit(0)})),process.on("message",(d=>{d?.type==="shutdown"&&(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",(d=>{if(RECOVERABLE_ERRNO.has(d?.code)){console.error(`[myhi] \u5DF2\u5FFD\u7565\u53EF\u6062\u590D\u5F02\u5E38(${d.code}):`,d.message);return}console.error("[myhi] \u672A\u6355\u83B7\u5F02\u5E38:",d.message),gracefulShutdown(),process.exit(1)})),process.on("unhandledRejection",(d=>{console.error("[myhi] \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD:",d)}));function readOrCreate(d,i){try{if((0,external_fs_.existsSync)(d))return(0,external_fs_.readFileSync)(d,"utf8").trim()}catch{}const n=i();return(0,external_fs_.writeFileSync)(d,n,{mode:384}),n}(function d(){try{const i=!(0,external_fs_.existsSync)((0,external_path_.join)(server_configDir,"token"))&&!(0,external_fs_.existsSync)((0,external_path_.join)(server_configDir,"password")),n=_readConfig();if(n.defaultTheme)return;n.defaultTheme=i?"light":"dark",(0,external_fs_.mkdirSync)(server_configDir,{recursive:!0}),(0,external_fs_.writeFileSync)((0,external_path_.join)(server_configDir,"config.json"),JSON.stringify(n,null,2))}catch{}})();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 d=Date.now();for(const[i,n]of userSessions)n.permanent||(!n.lastUsed||d-n.lastUsed>SESSION_MAX_AGE)&&userSessions.delete(i)}),3600*1e3);function getTailscaleIP(){try{return(0,external_child_process_namespaceObject.execSync)("tailscale ip -4",{timeout:3e3,stdio:"pipe"}).toString().trim().split(`
|
|
439
|
-
`)[0]}catch{}try{if(process.platform==="win32"){const d=(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(d)return d[1]}else try{const d=(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(d)return d[1]}catch{const d=(0,external_child_process_namespaceObject.execSync)("route -n get default 2>/dev/null || route -n 2>/dev/null",{timeout:3e3,stdio:"pipe"}).toString(),i=d.match(/interface:\s*(\S+)/i)||d.match(/0\.0\.0\.0\s+(\d+\.\d+\.\d+\.\d+)/);if(i){const n=(0,external_os_.networkInterfaces)()[i[1]];if(n){const t=n.find((e=>e.family==="IPv4"&&!e.internal));if(t)return t.address}if(/^\d+\.\d+\.\d+\.\d+$/.test(i[1]))return i[1]}}}catch{}for(const d of Object.values((0,external_os_.networkInterfaces)()))for(const i of d)if(i.family==="IPv4"&&!i.internal)return i.address;return"localhost"}function parseCookies(d=""){const i={};for(const n of d.split(";")){const t=n.indexOf("=");t>0&&(i[n.slice(0,t).trim()]=n.slice(t+1).trim())}return i}const SESSION_COOKIE="myhi_sid",SESSION_COOKIE_HTTP="myhi_sid_h",COOKIE_OPTS_BASE="HttpOnly; SameSite=Strict; Path=/; Max-Age=31536000",isSecureReq=d=>!!(d?.secure||d?.headers?.["x-forwarded-proto"]==="https");function cookieOpts(d){return isSecureReq(d)?COOKIE_OPTS_BASE+"; Secure":COOKIE_OPTS_BASE}function setSessionCookie(d,i,n){d.setHeader("Set-Cookie",`${isSecureReq(n)?SESSION_COOKIE:SESSION_COOKIE_HTTP}=${i||TOKEN}; ${cookieOpts(n)}`)}const CLEAR_SESSION_COOKIES=[SESSION_COOKIE,SESSION_COOKIE_HTTP].map((d=>`${d}=; HttpOnly; SameSite=Strict; Path=/; Max-Age=0`));function getSessionToken(d){const i=parseCookies(d),n=[i[SESSION_COOKIE],i[SESSION_COOKIE_HTTP]].filter(Boolean);return n.find((t=>userSessions.has(t)))||n[0]||null}function hasValidSession(d){const i=getSessionToken(d);if(i&&userSessions.has(i)){const n=userSessions.get(i);return n&&(n.lastUsed=Date.now()),!0}return!1}function getUserInfo(d){const i=getSessionToken(d);return i?userSessions.get(i):null}const app=express();app.set("trust proxy",!0),app.use(((d,i,n)=>{i.setHeader("Referrer-Policy","no-referrer"),i.setHeader("X-Content-Type-Options","nosniff"),n()}));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(d){const i=_readConfig()[d];return typeof i=="string"&&i?i: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)(((d,i)=>{const n=(d.headers.host||"").replace(/:\d+$/,"");i.writeHead(301,{Location:`https://${n}:${PORT}${d.url}`}),i.end()}))):(process.env.MYHI_NO_HTTPS||_readConfig().httpOnly?console.log("[myhi] \u6309\u8BBE\u7F6E\u4EE5 HTTP \u6A21\u5F0F\u8FD0\u884C\uFF08\u624B\u673A\u7B49\u975E\u672C\u673A\u6D4F\u89C8\u5668\u4E0D\u80FD\u7528\u9EA6\u514B\u98CE / \u6444\u50CF\u5934\uFF09\uFF1B\u5207\u56DE HTTPS\uFF1A\u7F51\u9875 \u8BBE\u7F6E \u203A \u670D\u52A1 \u203A \u8BBF\u95EE\u534F\u8BAE\uFF0C\u6216 myhi --https"):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 d of[httpsServer,httpServer])d&&(d.keepAliveTimeout=72e3,d.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({perMessageDeflate:{threshold:1024},serveClient:!1,cors:{origin:(d,i)=>{if(!d||_corsAllowed.test(d))return i(null,!0);i(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(d,i){if(!AUTO_ATTACH||_autoSpawned.has(d)||!process.env.DISPLAY&&process.platform==="linux")return;_autoSpawned.add(d);const n=(0,external_path_.join)(server_dirname,"attach.js"),t=process.execPath,e=i||"myhi";if(process.platform==="win32"){const s=`"${t}" "${n}" ${d}`,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",(f=>{console.warn("[attach] wt.exe \u5931\u8D25\uFF0C\u56DE\u9000\u5230 cmd:",f.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 "${t} ${n} ${d}"`;(0,external_child_process_namespaceObject.spawn)("osascript",["-e",s],{detached:!0,stdio:"ignore"}).unref()}else{const s=`${t} "${n}" ${d}`;for(const[u,f]of[["gnome-terminal",["--","bash","-c",`${s}; exec bash`]],["xterm",["-title",e,"-e",s]],["konsole",["--new-tab","-e",s]]]){const l=(0,external_child_process_namespaceObject.spawn)(u,f,{detached:!0,stdio:"ignore"});l.unref(),l.on("error",(()=>{}));break}}}const uploadDir=(0,external_path_.join)(server_configDir,"uploads");(0,external_fs_.mkdirSync)(uploadDir,{recursive:!0});function checkAuth(d,i,n){const t=d.query.token;if(t&&(t===TOKEN||userSessions.has(t))){const e=userSessions.get(t);if(e?.onetime){userSessions.delete(t);const f=(0,external_crypto_.randomBytes)(16).toString("hex");userSessions.set(f,{role:e.role,name:e.name,lastUsed:Date.now()}),setSessionCookie(i,f,d)}else setSessionCookie(i,t===TOKEN?TOKEN:t,d);const s=Object.keys(d.query).filter((f=>f!=="token")),u=d.path+(s.length?"?"+new URLSearchParams(Object.fromEntries(Object.entries(d.query).filter((([f])=>f!=="token")))):"");return i.redirect(u)}if(hasValidSession(d.headers.cookie)){if(isExclusiveMode()&&activeUser){const e=getSessionToken(d.headers.cookie);if(e!==TOKEN){const s=userSessions.get(e);if(!s||s.name!==activeUser.name)return i.setHeader("Set-Cookie",CLEAR_SESSION_COOKIES),i.redirect("/login")}}return n()}i.redirect("/login")}const _require=(0,external_module_namespaceObject.createRequire)(import.meta.url);function pkgDirSafe(d){try{return(0,external_path_.dirname)(_require.resolve(`${d}/package.json`))}catch{return null}}const libDir=(0,external_path_.join)(server_dirname,"lib"),staticOpts={maxAge:864e5};app.get("/theme.js",((d,i)=>{const n=_configString("defaultTheme");i.setHeader("Content-Type","application/javascript; charset=utf-8"),i.setHeader("Cache-Control","no-cache"),i.send(`window.MYHI_DEFAULT_THEME=${JSON.stringify(["light","dark","black","system"].includes(n)?n:"dark")};`)})),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:(d,i)=>{i.endsWith(".js")&&d.setHeader("Content-Type","application/javascript; charset=utf-8")}})),app.get("/manifest.json",((d,i)=>i.sendFile((0,external_path_.join)(server_dirname,"manifest.json")))),app.get("/icon.png",((d,i)=>i.sendFile((0,external_path_.join)(server_dirname,"icon.png")))),app.get("/icon.svg",((d,i)=>i.sendFile((0,external_path_.join)(server_dirname,"icon.svg"))));const _loginAttempts=new Map,LOGIN_MAX_ATTEMPTS=5,LOGIN_LOCKOUT_MS=300*1e3;function checkLoginRate(d){const i=Date.now(),n=_loginAttempts.get(d);return!n||i>n.resetAt?!0:n.count<LOGIN_MAX_ATTEMPTS}function recordLoginFailure(d){const i=Date.now(),n=_loginAttempts.get(d);!n||i>n.resetAt?_loginAttempts.set(d,{count:1,resetAt:i+LOGIN_LOCKOUT_MS}):n.count++}function clearLoginFailures(d){_loginAttempts.delete(d)}setInterval((()=>{const d=Date.now();for(const[i,n]of _loginAttempts)d>n.resetAt&&_loginAttempts.delete(i)}),600*1e3),app.get("/login",((d,i)=>{sendPage(d,i,"login.html")})),app.post("/login",express.urlencoded({extended:!1}),((d,i)=>{const n=d.ip;if(!checkLoginRate(n))return i.redirect("/login?error=locked");loadRoles(),loadUsers();const t=d.body?.password,e=d.query.from,s=e&&e.startsWith("/")&&!e.startsWith("//")?e:"/",u=hasUsers()?lookupUser(t):null;if(u){if(isExclusiveMode()&&activeUser&&activeUser.name!==u.name)return i.redirect("/login?error=occupied&user="+encodeURIComponent(activeUser.name));clearLoginFailures(n);const l=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(l,{role:memberRole(),member:!0,name:u.name,dir:u.dir,lastUsed:Date.now()}),isExclusiveMode()&&(activeUser?activeUser.tokens.add(l):activeUser={name:u.name,dir:u.dir,tokens:new Set([l]),loginAt:Date.now()}),setSessionCookie(i,l,d),console.log(`[\u767B\u5F55] ${u.name} \u767B\u5F55\uFF08${isMultiUser()?isExclusiveMode()?"\u72EC\u5360":"\u5171\u4EAB":"\u5355\u7528\u6237"}\u6A21\u5F0F\uFF09`),i.redirect(s)}const f=lookupPassword(t);if(f){clearLoginFailures(n);const l=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(l,{role:f.role,name:f.name,lastUsed:Date.now()}),setSessionCookie(i,l,d),i.redirect(s)}if(t===PASSWORD){clearLoginFailures(n);const l=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(l,{role:"admin",name:"\u7BA1\u7406\u5458",lastUsed:Date.now()}),setSessionCookie(i,l,d),i.redirect(s)}recordLoginFailure(n),i.redirect("/login?error=1")})),app.post("/logout",((d,i)=>{const n=getSessionToken(d.headers.cookie);n&&(activeUser&&activeUser.tokens.has(n)&&(activeUser.tokens.delete(n),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(n)),i.setHeader("Set-Cookie",CLEAR_SESSION_COOKIES),i.redirect("/login")})),app.get("/api/status",((d,i)=>{if(isExclusiveMode()&&activeUser)return i.json({occupied:!0,userName:activeUser.name,releasing:!!_exclusiveReleaseTimer});if(isMultiUser()&&!isExclusiveMode()){const n=new Set;for(const[,t]of io.sockets.sockets){if(!t.data.userName||t.data.userName==="\u7BA1\u7406\u5458")continue;const e=t.handshake.headers.cookie;e&&!hasValidSession(e)||n.add(t.data.userName)}return i.json({occupied:!1,onlineUsers:[...n]})}i.json({occupied:!1})}));const _gzFresh=new Map;function gzFresh(d){try{const i=(0,external_fs_.statSync)(d),n=i.size+":"+i.mtimeMs,t=_gzFresh.get(d);if(t&&t.key===n)return t.ok;const e=(0,external_fs_.openSync)(d+".gz","r"),s=Buffer.alloc(4);try{(0,external_fs_.readSync)(e,s,0,4,(0,external_fs_.fstatSync)(e).size-4)}finally{(0,external_fs_.closeSync)(e)}const u=s.readUInt32LE(0)===i.size>>>0;return _gzFresh.set(d,{key:n,ok:u}),u}catch{return!1}}function sendPage(d,i,n){const t=(0,external_path_.join)(server_dirname,n);if(gzFresh(t)&&/\bgzip\b/.test(d.headers["accept-encoding"]||""))return i.setHeader("Content-Type","text/html; charset=UTF-8"),i.setHeader("Content-Encoding","gzip"),i.setHeader("Vary","Accept-Encoding"),i.sendFile(t+".gz");i.sendFile(t)}app.get("/admin",((d,i)=>sendPage(d,i,"admin.html"))),app.get("/",checkAuth,((d,i)=>sendPage(d,i,"index.html"))),app.get("/terminal/:id",checkAuth,((d,i)=>sendPage(d,i,"chat.html"))),app.get("/grid",checkAuth,((d,i)=>sendPage(d,i,"grid.html"))),app.get("/terminal-raw/:id",checkAuth,((d,i)=>sendPage(d,i,"terminal.html"))),app.use("/lib",express.static((0,external_path_.join)(server_dirname,"lib"),{maxAge:0,setHeaders:d=>d.setHeader("Cache-Control","no-cache")}));const migrateTmp=(0,external_path_.join)(server_configDir,"migrate-tmp"),_migrateUploads=new Map;try{(0,external_fs_.rmSync)(migrateTmp,{recursive:!0,force:!0})}catch{}setInterval((()=>{for(const[d,i]of _migrateUploads)if(Date.now()-i.at>36e5){try{(0,external_fs_.rmSync)(i.file,{force:!0})}catch{}_migrateUploads.delete(d)}}),6e5).unref();function migrateSess(d,i){const n=getUserInfo(d.headers.cookie),t=manager.get(d.params.id);return!t||t.mode!=="agent"?(i.status(404).json({ok:!1,error:"\u4EFB\u52A1\u4E0D\u5B58\u5728"}),null):n&&n.role!=="admin"&&t.owner&&t.owner!==n.name?(i.status(403).json({ok:!1,error:"\u4E0D\u80FD\u5BFC\u51FA\u522B\u4EBA\u7684\u4EFB\u52A1"}),null):t}app.get("/api/migrate/:id/preview",checkAuth,((d,i)=>{const n=migrateSess(d,i);n&&i.json({ok:!0,...exportPreview(n),excludeDirs:EXCLUDE_DIRS})})),app.get("/api/migrate/:id/export",checkAuth,(async(d,i)=>{const n=migrateSess(d,i);if(!n)return;const t=new Date,e=`${t.getFullYear()}${String(t.getMonth()+1).padStart(2,"0")}${String(t.getDate()).padStart(2,"0")}`,s=`${String(n.title||"task").replace(/[\\/:*?"<>|]+/g,"_").slice(0,60)}-${e}${PACK_EXT}`;i.setHeader("Content-Type","application/gzip"),i.setHeader("Content-Disposition",`attachment; filename="myhi-task${PACK_EXT}"; filename*=UTF-8''${encodeURIComponent(s)}`);try{await exportTask(n,{conv:d.query.conv!=="0",mem:d.query.mem!=="0",from:machineName()},i)}catch(u){console.error("[\u8FC1\u79FB] \u5BFC\u51FA\u5931\u8D25:",u.message),i.destroy(u)}console.log(`[\u8FC1\u79FB] \u5BFC\u51FA\u4EFB\u52A1\u300C${n.title}\u300D(${n.id}) conv=${d.query.conv!=="0"} mem=${d.query.mem!=="0"}`)})),app.post("/api/migrate/upload",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie);if(n&&!hasPermission(n.role,"operator"))return i.status(403).json({ok:!1,error:"\u4F60\u7684\u89D2\u8272\u4E0D\u80FD\u5BFC\u5165\u4EFB\u52A1"});(0,external_fs_.mkdirSync)(migrateTmp,{recursive:!0}),multer({dest:migrateTmp,limits:{fileSize:8*1024**3}}).single("pack")(d,i,(async t=>{if(t)return i.status(400).json({ok:!1,error:t.message});if(!d.file)return i.status(400).json({ok:!1,error:"\u6CA1\u6709\u6536\u5230\u6587\u4EF6"});try{const e=await readManifest(d.file.path),s=(0,external_crypto_.randomBytes)(12).toString("hex");_migrateUploads.set(s,{file:d.file.path,user:n?.name||null,at:Date.now()}),i.json({ok:!0,token:s,manifest:e,userDir:n?.dir||null})}catch(e){try{(0,external_fs_.rmSync)(d.file.path,{force:!0})}catch{}i.status(400).json({ok:!1,error:/incorrect header|unexpected end|invalid/i.test(e.message)?"\u6587\u4EF6\u4E0D\u662F\u6709\u6548\u7684 myhi \u8FC1\u79FB\u5305\uFF08\u53EF\u80FD\u4E0B\u8F7D\u4E0D\u5B8C\u6574\u6216\u4E0D\u662F .myhipack\uFF09":e.message})}}))})),app.post("/api/migrate/import",checkAuth,express.json(),(async(d,i)=>{const n=getUserInfo(d.headers.cookie),t=_migrateUploads.get(String(d.body?.token||""));if(!t||t.user&&t.user!==(n?.name||null))return i.status(400).json({ok:!1,error:"\u4E0A\u4F20\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8FC1\u79FB\u5305"});const e=String(d.body?.cwd||"").trim();if(!e||!(0,external_path_.isAbsolute)(e))return i.status(400).json({ok:!1,error:"\u8BF7\u586B\u5199\u5B8C\u6574\u7684\u76EE\u6807\u76EE\u5F55\uFF08\u7EDD\u5BF9\u8DEF\u5F84\uFF09"});const s=(0,external_path_.resolve)((0,external_path_.normalize)(e));if(n?.dir){const u=(0,external_path_.resolve)((0,external_path_.normalize)(n.dir));if(s!==u&&!s.startsWith(u+external_path_.sep))return i.status(403).json({ok:!1,error:`\u53EA\u80FD\u5BFC\u5165\u5230\u4F60\u7684\u76EE\u5F55 ${u} \u91CC`})}try{if((0,external_fs_.existsSync)(s)&&(0,external_fs_.readdirSync)(s).length)return i.status(409).json({ok:!1,error:"\u76EE\u6807\u76EE\u5F55\u5DF2\u5B58\u5728\u4E14\u4E0D\u662F\u7A7A\u7684\u3002\u6362\u4E00\u4E2A\u76EE\u5F55\u540D\uFF0C\u907F\u514D\u8986\u76D6\u5DF2\u6709\u6587\u4EF6"})}catch{}try{const{manifest:u,sid:f,memory:l}=await importPack(t.file,s),o=manager.createAgent({title:u.title||"\u8FC1\u79FB\u7684\u4EFB\u52A1",cwd:s,tags:u.tags||[],firstUserText:u.firstUserText||"",resumeSessionId:f||void 0,owner:n?.name,userDir:n?.dir});broadcastSessions();try{(0,external_fs_.rmSync)(t.file,{force:!0})}catch{}_migrateUploads.delete(String(d.body.token)),console.log(`[\u8FC1\u79FB] \u5BFC\u5165\u4EFB\u52A1\u300C${u.title}\u300D\u2192 ${s}\uFF08\u6765\u81EA ${u.from||"?"}\uFF0C\u5BF9\u8BDD=${!!f}\uFF09`),i.json({ok:!0,id:o.id,conv:!!f,memory:l,secrets:u.secrets||[]})}catch(u){console.error("[\u8FC1\u79FB] \u5BFC\u5165\u5931\u8D25:",u.message),i.status(500).json({ok:!1,error:"\u5BFC\u5165\u5931\u8D25\uFF1A"+u.message})}})),app.get("/api/sessions",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie);i.json(manager.list(n?.name,n?.role==="admin"))})),app.get("/api/usage",((d,i)=>{try{const n=manager.listSessions().filter((e=>e.mode==="agent"&&e.alive)).map((e=>({id:e.id,title:e.title,owner:e.owner,usage:e._usage})));let t=null;for(const e of n)if(e.usage?.rateLimitInfo){t=e.usage.rateLimitInfo;break}i.json({rateLimit:t,activeSessions:n})}catch(n){i.status(500).json({error:n.message})}})),app.post("/api/sessions",checkAuth,express.json(),((d,i)=>{const n=getUserInfo(d.headers.cookie),t=manager.create({...d.body,owner:n?.name,userDir:n?.dir});i.status(201).json(t.toJSON())})),app.delete("/api/sessions/:id",checkAuth,((d,i)=>{manager.kill(d.params.id),i.status(204).end()})),app.get("/api/sessions/health",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie),t=manager.listSessions().filter((e=>e.mode==="agent")).filter((e=>!e.owner||!n?.name||e.owner===n.name)).map((e=>({...e.toJSON(),health:getSessionHealth(e.claudeSessionId)})));i.json({ok:!0,sessions:t})})),app.post("/api/sessions/:id/reset",checkAuth,((d,i)=>{const n=manager.get(d.params.id);if(!n||n.mode!=="agent"||typeof n.reset!="function")return i.status(404).json({ok:!1,error:"agent \u4F1A\u8BDD\u4E0D\u5B58\u5728"});n.reset(),console.log(`[reset] \u4F1A\u8BDD ${n.id}\u300C${n.title||""}\u300D\u88AB\u91CD\u5F00\u4E3A\u5E72\u51C0\u4F1A\u8BDD\uFF08\u4F1A\u8BDD\u4F53\u68C0\uFF0Cby ${getUserInfo(d.headers.cookie)?.name||"\u7BA1\u7406\u5458"}\uFF09`),n.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(),i.json({ok:!0})})),app.get("/api/claude-sessions",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie);i.json(listLocalClaudeSessions(n?.dir))}));function sendJsonMaybeGz(d,i,n){const t=Buffer.from(JSON.stringify(n));if(i.setHeader("Content-Type","application/json; charset=utf-8"),i.setHeader("Vary","Accept-Encoding"),t.length>4096&&/\bgzip\b/.test(d.headers["accept-encoding"]||""))return i.setHeader("Content-Encoding","gzip"),i.end((0,external_zlib_.gzipSync)(t));i.end(t)}app.get("/api/agent/history/:sessionId",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n||n.mode!=="agent")return i.status(404).json({ok:!1,error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=n.claudeSessionId;if(!t)return i.json({ok:!0,messages:[],total:0,hasMore:!1});const e=Math.max(0,parseInt(d.query.offset,10)||0),s=Math.min(200,Math.max(1,parseInt(d.query.limit,10)||50)),u=readTranscript(t,{offset:e,limit:s});sendJsonMaybeGz(d,i,{ok:!0,messages:u.messages,total:u.total,hasMore:u.hasMore})})),app.get("/api/dirs",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie);if(!n||n.role!=="admin")return i.status(403).json({error:"\u6CA1\u6709\u76EE\u5F55\u6D4F\u89C8\u6743\u9650"});const t=n.dir?(0,external_path_.resolve)((0,external_path_.normalize)(n.dir)):null,e=process.platform==="win32"?"\\":"/";let s=d.query.path||t||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+="\\"),t&&!u.startsWith(t)&&(u=t);try{const f=(0,external_fs_.readdirSync)(u,{withFileTypes:!0}).filter((c=>c.isDirectory()&&c.name!==".git")).map((c=>({name:c.name,path:u.replace(/[/\\]+$/,"")+e+c.name}))).sort(((c,r)=>c.name.localeCompare(r.name))),l=(0,external_path_.join)(u,".."),o=!t||(0,external_path_.resolve)((0,external_path_.normalize)(l)).startsWith(t);i.json({current:u,parent:o&&l!==u?l:null,dirs:f,drives:process.platform==="win32"&&!t?"CDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((c=>c+":\\")).filter((c=>{try{return(0,external_fs_.existsSync)(c)}catch{return!1}})):[]})}catch(f){i.status(400).json({error:f.message})}}));function safePath(d,i){const n=(0,external_path_.resolve)((0,external_path_.normalize)(d)),t=(0,external_path_.resolve)((0,external_path_.normalize)((0,external_path_.join)(d,i||"")));if(t!==n&&!t.startsWith(n+external_path_.sep))return null;try{const e=(0,external_fs_.realpathSync)(n),s=(0,external_fs_.existsSync)(t)?(0,external_fs_.realpathSync)(t):t;if(s!==e&&!s.startsWith(e+external_path_.sep))return null}catch{}return t}function server_walkFiles(d,i,n=[],t=0,e=[],s=!1,u=1/0){if(t>20||n.length>=u)return n;let f;try{f=(0,external_fs_.readdirSync)(d,{withFileTypes:!0})}catch{return n}for(const l of f){if(l.name===".git"||e.includes(l.name))continue;if(n.length>=u)return n;const o=(0,external_path_.join)(d,l.name),c=i?i+"/"+l.name:l.name;try{const r=(0,external_fs_.lstatSync)(o);if(r.isSymbolicLink())continue;r.isDirectory()?(s&&n.push({name:c,dir:!0,mtime:r.mtimeMs}),server_walkFiles(o,c,n,t+1,e,s,u)):r.isFile()&&n.push({name:c,size:r.size,mtime:r.mtimeMs})}catch{}}return n}function fileHash(d){return new Promise(((i,n)=>{const t=(0,external_crypto_.createHash)("sha256"),e=(0,external_fs_.createReadStream)(d);e.on("data",(s=>t.update(s))),e.on("end",(()=>i(t.digest("hex")))),e.on("error",n)}))}app.get("/api/files/:sessionId",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=d.query.path||"",e=safePath(n.cwd,t);if(!e)return i.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});try{if(!(0,external_fs_.statSync)(e).isDirectory())return i.status(400).json({error:"\u4E0D\u662F\u76EE\u5F55"});const s=(0,external_fs_.readdirSync)(e,{withFileTypes:!0}).filter((l=>l.name!==".git")).map((l=>{const o=(0,external_path_.join)(e,l.name);try{const c=(0,external_fs_.lstatSync)(o);return c.isSymbolicLink()?null:{name:l.name,isDir:c.isDirectory(),size:c.isFile()?c.size:void 0,mtime:c.mtimeMs}}catch{return null}})).filter(Boolean).sort(((l,o)=>o.isDir-l.isDir||l.name.localeCompare(o.name))),u=t?t.replace(/\\/g,"/"):"",f=u.includes("/")?u.slice(0,u.lastIndexOf("/")):u?"":null;i.json({ok:!0,cwd:n.cwd,path:u,parent:f,entries:s})}catch(s){i.status(500).json({error:s.message})}})),app.get("/api/files/:sessionId/search",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=String(d.query.q||"").trim().toLowerCase();try{let e=server_walkFiles(n.cwd,"",[],0,["node_modules"],!0).map((u=>({name:u.name,dir:!!u.dir,mtime:u.mtime})));t&&(e=e.filter((u=>u.name.toLowerCase().includes(t))));const s=u=>{if(!t)return 0;const f=u.name.slice(u.name.lastIndexOf("/")+1).toLowerCase();return f.startsWith(t)?0:f.includes(t)?1:2};e.sort(((u,f)=>s(u)-s(f)||(f.mtime||0)-(u.mtime||0))),i.json({ok:!0,files:e.slice(0,50).map((u=>({name:u.name,dir:!!u.dir})))})}catch(e){i.status(500).json({error:e.message})}})),app.get("/api/files/:sessionId/at-ls",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=process.platform==="win32",e=String(d.query.dir||"").replace(/\\/g,"/"),s=String(d.query.q||"").toLowerCase(),u=l=>l.replace(/\\/g,"/");if(t&&e==="/"){const l="CDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((o=>o+":")).filter((o=>{try{return(0,external_fs_.existsSync)(o+"\\")}catch{return!1}})).filter((o=>!s||o.toLowerCase().startsWith(s))).map((o=>({label:o,dir:!0})));return i.json({ok:!0,win:t,abs:"/",rel:!1,parent:null,entries:l})}let f;e?e==="~"||e.startsWith("~/")?f=(0,external_path_.join)((0,external_os_.homedir)(),e.slice(1)):t&&/^[A-Za-z]:/.test(e)?f=e.length===2?e+"/":e:e.startsWith("/")?f=e:f=(0,external_path_.join)(n.cwd,e):f=n.cwd,f=(0,external_path_.resolve)((0,external_path_.normalize)(f));try{const l=(0,external_fs_.readdirSync)(f,{withFileTypes:!0}).filter((a=>a.name!==".git")).map((a=>{try{const h=(0,external_fs_.lstatSync)((0,external_path_.join)(f,a.name));return h.isSymbolicLink()||!(h.isDirectory()||h.isFile())?null:{label:a.name,dir:h.isDirectory()}}catch{return null}})).filter(Boolean),o=a=>s?a.label.toLowerCase().startsWith(s)?0:1:0,c=l.filter((a=>!s||a.label.toLowerCase().includes(s))).filter((a=>s.startsWith(".")||!a.label.startsWith("."))).sort(((a,h)=>o(a)-o(h)||h.dir-a.dir||a.label.localeCompare(h.label,"zh"))).slice(0,300),r=(0,external_path_.dirname)(f);i.json({ok:!0,win:t,abs:u(f),rel:!e||!/^([/~]|[A-Za-z]:)/.test(e),parent:r!==f?u(r):t?"/":null,entries:c})}catch(l){i.status(l.code==="ENOENT"||l.code==="ENOTDIR"?404:500).json({error:l.code==="ENOENT"?"\u76EE\u5F55\u4E0D\u5B58\u5728":l.code==="ENOTDIR"?"\u4E0D\u662F\u76EE\u5F55":l.message})}}));const _viewTokens=new Map;app.post("/api/files/:sessionId/view-token",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({ok:!1,error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=Date.now();for(const[s,u]of _viewTokens)u.exp<t&&_viewTokens.delete(s);let e=[..._viewTokens].find((([,s])=>s.sid===n.id&&s.cwd===n.cwd&&s.exp-t>36e5))?.[0];e||(e=(0,external_crypto_.randomBytes)(18).toString("base64url"),_viewTokens.set(e,{sid:n.id,cwd:n.cwd,exp:t+2*36e5})),i.json({ok:!0,token:e,cwd:n.cwd})})),app.get("/view/:token/*",((d,i)=>{const n=_viewTokens.get(d.params.token);if(!n||n.exp<Date.now())return i.status(403).send("\u9884\u89C8\u94FE\u63A5\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u56DE\u5230 myhi \u91CD\u65B0\u6253\u5F00");const t=safePath(n.cwd,d.params[0]||"");if(!t)return i.status(403).send("\u8DEF\u5F84\u8D8A\u754C");i.setHeader("Content-Security-Policy","sandbox allow-scripts allow-popups allow-forms allow-modals allow-downloads"),i.setHeader("X-Content-Type-Options","nosniff"),i.setHeader("Cache-Control","no-cache"),i.sendFile(t,{dotfiles:"allow"},(e=>{e&&!i.headersSent&&i.status(404).send("\u6587\u4EF6\u4E0D\u5B58\u5728")}))}));const _zipTickets=new Map;app.post("/api/files/:sessionId/zip-ticket",checkAuth,express.json({limit:"1mb"}),((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({ok:!1,error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=Array.isArray(d.body?.paths)?d.body.paths.map(String).filter(Boolean).slice(0,2e3):[];if(!t.length)return i.status(400).json({ok:!1,error:"\u6CA1\u6709\u9009\u62E9\u8981\u4E0B\u8F7D\u7684\u6587\u4EF6"});const e=[];for(const a of t){const h=safePath(n.cwd,a);if(!h)return i.status(403).json({ok:!1,error:"\u8DEF\u5F84\u8D8A\u754C\uFF1A"+a});e.push({abs:h,name:a.replace(/\\/g,"/").replace(/\/+$/,"").split("/").pop()})}const{files:s,bytes:u,skipped:f}=collectZipFiles(e);if(!s.length)return i.status(400).json({ok:!1,error:"\u9009\u4E2D\u7684\u5185\u5BB9\u91CC\u6CA1\u6709\u6587\u4EF6\uFF08\u7A7A\u6587\u4EF6\u5939\uFF0C\u6216\u53EA\u6709\u88AB\u8DF3\u8FC7\u7684 .git / node_modules \u7B49\uFF09"});if(s.length>ZIP_MAX_FILES)return i.status(413).json({ok:!1,error:`\u6587\u4EF6\u592A\u591A\uFF08\u8D85\u8FC7 ${ZIP_MAX_FILES} \u4E2A\uFF09\uFF0C\u8BF7\u5206\u51E0\u6279\u4E0B\u8F7D`});if(u>ZIP_MAX_BYTES)return i.status(413).json({ok:!1,error:`\u603B\u5927\u5C0F ${(u/1024**3).toFixed(1)} GB \u8D85\u8FC7 4GB\uFF0C\u8BF7\u5206\u51E0\u6279\u4E0B\u8F7D\uFF08\u6216\u7528\u9996\u9875\u4EFB\u52A1 \u22EF \u2192\u300C\u8FC1\u79FB\u5230\u53E6\u4E00\u53F0 myhi\u300D\u6253\u5305\uFF09`});const l=Date.now();for(const[a,h]of _zipTickets)h.exp<l&&_zipTickets.delete(a);const c=(e.length===1?e[0].name:null)||`${String(n.title||"files").replace(/[\\/:*?"<>|]+/g,"_").slice(0,40)}-${e.length}\u9879`,r=(0,external_crypto_.randomBytes)(12).toString("hex");_zipTickets.set(r,{sid:n.id,files:s,name:c+".zip",exp:l+10*6e4}),i.json({ok:!0,ticket:r,name:c+".zip",files:s.length,bytes:u,skipped:f})})),app.get("/api/files/:sessionId/zip",checkAuth,(async(d,i)=>{const n=_zipTickets.get(String(d.query.ticket||""));if(!n||n.sid!==d.params.sessionId||n.exp<Date.now())return i.status(410).send("\u4E0B\u8F7D\u94FE\u63A5\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u56DE\u5230 myhi \u91CD\u65B0\u70B9\u4E0B\u8F7D");_zipTickets.delete(String(d.query.ticket)),i.setHeader("Content-Type","application/zip"),i.setHeader("Content-Disposition",`attachment; filename="download.zip"; filename*=UTF-8''${encodeURIComponent(n.name)}`);try{await writeZip(i,n.files),i.end()}catch(t){console.warn("[files] \u6253\u5305\u4E0B\u8F7D\u4E2D\u65AD:",t.message),i.destroy()}})),app.get("/api/files/:sessionId/download",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=d.query.path;if(!t)return i.status(400).json({error:"\u7F3A\u5C11 path \u53C2\u6570"});const e=safePath(n.cwd,t);if(!e)return i.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});let s;try{s=(0,external_fs_.statSync)(e)}catch{return i.status(404).json({error:"\u6587\u4EF6\u4E0D\u5B58\u5728"})}if(!s.isFile())return i.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});const u=t.split("/").pop(),f=d.query.inline==="1"&&/\.(png|jpe?g|gif|webp|bmp|ico|avif|svg|pdf|mp4|webm|ogv|mov|m4v|mp3|wav|ogg|oga|m4a|flac|aac|opus)$/i.test(u);i.setHeader("Content-Disposition",`${f?"inline":"attachment"}; filename*=UTF-8''${encodeURIComponent(u)}`),f&&/\.svg$/i.test(u)&&i.setHeader("Content-Security-Policy","sandbox; default-src 'none'; img-src data:; style-src 'unsafe-inline'"),i.sendFile(e,{dotfiles:"allow",acceptRanges:!0},(l=>{if(!l)return;const o=l.code||"";["ECONNABORTED","EPIPE","ECONNRESET"].includes(o)||i.writableEnded||(console.warn("[files] \u4E0B\u8F7D\u5931\u8D25:",t,o||l.message),i.headersSent?i.destroy():i.status(500).json({error:"\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: "+(o||l.message)}))}))})),app.post("/api/files/:sessionId/upload",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=(d.query.path||"").replace(/\\/g,"/"),e=safePath(n.cwd,t);if(!e)return i.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});(0,external_fs_.mkdirSync)(e,{recursive:!0}),multer({storage:multer.diskStorage({destination:(s,u,f)=>{u.originalname=Buffer.from(u.originalname,"latin1").toString("utf8");const l=u.originalname.includes("/")?u.originalname.slice(0,u.originalname.lastIndexOf("/")):"",o=l?(0,external_path_.join)(e,l):e,c=(0,external_path_.resolve)((0,external_path_.normalize)(o)),r=(0,external_path_.resolve)((0,external_path_.normalize)(n.cwd));if(c!==r&&!c.startsWith(r+external_path_.sep))return f(new Error("\u8DEF\u5F84\u8D8A\u754C"));(0,external_fs_.mkdirSync)(o,{recursive:!0}),f(null,o)},filename:(s,u,f)=>{const l=u.originalname.includes("/")?u.originalname.slice(u.originalname.lastIndexOf("/")+1):u.originalname;f(null,l)}}),limits:{fileSize:500*1024*1024}}).array("files",100)(d,i,(s=>{if(s)return i.status(400).json({error:s.message});if(!d.files?.length)return i.status(400).json({error:"\u6CA1\u6709\u6587\u4EF6"});const u=d.files.map((f=>({name:f.originalname,size:f.size,path:(0,external_path_.resolve)(f.path).replace(/\\/g,"/")})));io.emit("files:changed",{sessionId:n.id}),i.json({ok:!0,files:u})}))})),app.delete("/api/files/:sessionId",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=d.query.path;if(!t)return i.status(400).json({error:"\u7F3A\u5C11 path \u53C2\u6570"});const e=safePath(n.cwd,t);if(!e)return i.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)(n.cwd)))return i.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:n.id}),i.json({ok:!0})}catch(s){i.status(500).json({error:s.message})}})),app.get("/api/files/:sessionId/manifest",checkAuth,(async(d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=d.query.path||"",e=safePath(n.cwd,t);if(!e)return i.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});try{const s=server_walkFiles(e,""),u=[];for(const f of s){if(f.size>=50*1024*1024){u.push(f);continue}try{const l=await fileHash((0,external_path_.join)(e,f.name));u.push({...f,hash:l})}catch{u.push(f)}}i.json({ok:!0,cwd:n.cwd,path:t,files:u})}catch(s){i.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(d){return String(d||"").replace(/\\/g,"/").replace(/^\/+/,"")}function editableTarget(d,i){const n=normRelPath(i);if(!n)return{error:"\u7F3A\u5C11 path",code:400};const t=safePath(d.cwd,n);if(!t)return{error:"\u8DEF\u5F84\u8D8A\u754C",code:403};const e=(n.split("/").pop().match(/\.([A-Za-z0-9]+)$/)||[])[1]?.toLowerCase()||"";return EDITABLE_EXTS.has(e)?{rel:n,target:t}:{error:"\u8BE5\u7C7B\u578B\u6587\u4EF6\u4E0D\u652F\u6301\u5728\u7EBF\u7F16\u8F91\uFF0C\u8BF7\u7528\u4E0B\u8F7D",code:415}}function looksBinary(d){const i=Math.min(d.length,8192);for(let n=0;n<i;n++)if(d[n]===0)return!0;return!1}function findBySuffix(d,i){const n=server_walkFiles(d,"",[],0,["node_modules"],!1,2e4).filter((e=>e.name.endsWith("/"+i)));if(!n.length)return null;const t=e=>e.name.split("/").length;return n.sort(((e,s)=>t(e)-t(s)||s.mtime-e.mtime)),n[0].name}app.get("/api/files/:sessionId/content",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});let t=editableTarget(n,d.query.path);if(t.error)return i.status(t.code).json({error:t.error});if(!(0,external_fs_.existsSync)(t.target)&&!(0,external_path_.isAbsolute)(t.rel)){const u=findBySuffix(n.cwd,t.rel);u&&(t=editableTarget(n,u))}let e;try{e=(0,external_fs_.statSync)(t.target)}catch{return i.status(404).json({error:"\u6587\u4EF6\u4E0D\u5B58\u5728"})}if(!e.isFile())return i.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});if(e.size>EDIT_MAX_BYTES)return i.status(413).json({error:"\u6587\u4EF6\u8D85\u8FC7 2MB\uFF0C\u4EC5\u652F\u6301\u4E0B\u8F7D"});let s;try{s=(0,external_fs_.readFileSync)(t.target)}catch(u){return i.status(500).json({error:"\u8BFB\u53D6\u5931\u8D25: "+(u.code||u.message)})}if(looksBinary(s))return i.status(415).json({error:"\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u4EC5\u652F\u6301\u4E0B\u8F7D"});i.json({ok:!0,path:t.rel,name:t.rel.split("/").pop(),content:s.toString("utf8"),mtime:e.mtimeMs,size:e.size,md:/\.(md|markdown)$/i.test(t.rel)})})),app.put("/api/files/:sessionId/content",checkAuth,express.json({limit:"4mb"}),((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{content:t,baseMtime:e,force:s}=d.body||{};if(typeof t!="string")return i.status(400).json({error:"\u7F3A\u5C11\u5185\u5BB9"});if(Buffer.byteLength(t,"utf8")>EDIT_MAX_BYTES)return i.status(413).json({error:"\u5185\u5BB9\u8D85\u8FC7 2MB"});const u=editableTarget(n,d.body.path);if(u.error)return i.status(u.code).json({error:u.error});let f;try{f=(0,external_fs_.statSync)(u.target)}catch{return i.status(404).json({error:"\u6587\u4EF6\u5DF2\u88AB\u5220\u9664\uFF0C\u65E0\u6CD5\u4FDD\u5B58"})}if(!f.isFile())return i.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});if(!s&&typeof e=="number"&&Math.abs(f.mtimeMs-e)>300)return i.status(409).json({error:"conflict",mtime:f.mtimeMs});const l=u.target+".myhi-edit-"+Date.now();try{try{(0,external_fs_.writeFileSync)(l,t,"utf8"),(0,external_fs_.renameSync)(l,u.target)}catch{try{(0,external_fs_.rmSync)(l,{force:!0})}catch{}(0,external_fs_.writeFileSync)(u.target,t,"utf8")}}catch(c){const r=["EBUSY","EPERM","EACCES"].includes(c.code);return console.warn("[files] \u4FDD\u5B58\u5931\u8D25:",u.rel,c.code||c.message),i.status(500).json({error:r?"\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: "+(c.code||c.message)})}let o=Date.now();try{o=(0,external_fs_.statSync)(u.target).mtimeMs}catch{}io.emit("files:changed",{sessionId:n.id}),i.json({ok:!0,mtime:o})})),app.get("/api/me",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie);i.json({name:n?.name||"\u7528\u6237",role:n?.role||"admin",exclusive:isExclusiveMode(),hasUsers:hasUsers(),multiUser:isMultiUser(),member:!!n?.member,dir:n?.dir||null,defaultRoot:n?.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,((d,i)=>{const n=loadGateway();i.json({baseUrl:n.baseUrl||"",apiKey:n.apiKey?n.apiKey.length>12?n.apiKey.slice(0,6)+"***"+n.apiKey.slice(-4):"***":"",hasKey:!!n.apiKey})})),app.post("/api/gateway",checkAdminAuth,express.json(),((d,i)=>{const{baseUrl:n,apiKey:t}=d.body||{},e=loadGateway(),s={baseUrl:typeof n=="string"?n.trim():e.baseUrl,apiKey:!t||t.includes("***")?e.apiKey:t.trim()};try{(0,external_fs_.mkdirSync)(server_configDir,{recursive:!0}),(0,external_fs_.writeFileSync)(gatewayFile,JSON.stringify(s,null,2),{mode:384}),i.json({ok:!0})}catch(u){i.status(500).json({error:u.message})}})),app.get("/api/secrets",checkAdminAuth,((d,i)=>{try{i.json(secretsOverview())}catch(n){i.status(500).json({error:n.message})}})),app.post("/api/secrets",checkAdminAuth,express.json(),((d,i)=>{const{name:n,value:t,type:e,scope:s,cwd:u}=d.body||{},f=upsertSecret({name:n,value:t,type:e,scope:s,cwd:u});if(f.error)return i.status(400).json(f);i.json(f)})),app.delete("/api/secrets",checkAdminAuth,express.json(),((d,i)=>{const{name:n,scope:t,cwd:e}=d.body||{};if(!n)return i.status(400).json({error:"\u7F3A\u5C11 name"});try{i.json(deleteSecret({name:n,scope:t,cwd:e}))}catch(s){i.status(500).json({error:s.message})}})),app.get("/api/session/:id/secrets",checkAuth,((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});i.json({cwd:n.cwd,project:listSecrets("project",n.cwd),global:listSecrets("global")})})),app.post("/api/session/:id/secrets",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:t,value:e,type:s}=d.body||{},u=upsertSecret({name:t,value:e,type:s,scope:"project",cwd:n.cwd});if(u.error)return i.status(400).json(u);i.json(u)})),app.delete("/api/session/:id/secrets",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:t}=d.body||{};if(!t)return i.status(400).json({error:"\u7F3A\u5C11 name"});i.json(deleteSecret({name:t,scope:"project",cwd:n.cwd}))})),app.post("/api/session/:id/secrets/bulk",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=upsertManyProject(n.cwd,(d.body||{}).text||"");if(t.error)return i.status(400).json(t);i.json(t)})),app.get("/api/session/:id/guard",checkAuth,((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=getProjectGuard(n.cwd);i.json({cwd:n.cwd,enabled:t.enabled,level:t.level,entities:t.entities})})),app.put("/api/session/:id/guard",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{enabled:t,level:e}=d.body||{},s=setProjectGuard(n.cwd,{enabled:t,level:e});if(s.error)return i.status(400).json(s);i.json(s)})),app.post("/api/session/:id/guard/entity",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:t,type:e}=d.body||{},s=upsertEntity(n.cwd,{name:t,type:e});if(s.error)return i.status(400).json(s);i.json(s)})),app.delete("/api/session/:id/guard/entity",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:t}=d.body||{};if(!t)return i.status(400).json({error:"\u7F3A\u5C11 name"});i.json(deleteEntity(n.cwd,t))})),app.post("/api/session/:id/guard/bulk",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=upsertManyEntities(n.cwd,(d.body||{}).text||"");if(t.error)return i.status(400).json(t);i.json(t)})),app.get("/api/session/:id/guard/audit",checkAuth,((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=n.claudeSessionId||d.params.id;i.json({entries:loadAudit(t)})})),app.get("/api/session/:id/followup",checkAuth,((d,i)=>{const n=manager.get(d.params.id);if(!n||typeof n.followUpState!="function")return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728\u6216\u975E AI \u4F1A\u8BDD"});i.json(n.followUpState())})),app.put("/api/session/:id/followup",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n||typeof n.setFollowUp!="function")return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728\u6216\u975E AI \u4F1A\u8BDD"});const{enabled:t,intervalMinutes:e}=d.body||{};i.json(n.setFollowUp({enabled:t,intervalMinutes:e}))}));function maybeKickRelay(d){try{if(!d?.autoSend)return;const i=manager.get(d.sessionId);i&&typeof i._maybeRelayDraft=="function"&&i.alive&&!i.isBusy&&i._maybeRelayDraft()}catch{}}app.get("/api/inbox",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie),{sessionId:t}=d.query;try{try{rebindDrafts(manager.listSessions())}catch{}const e=new Set(manager.list(n?.name,n?.role==="admin").map((l=>l.id))),s=listDrafts({sessionId:t||void 0}).filter((l=>e.has(l.sessionId)||l.owner&&l.owner===n?.name)),u={};for(const l of s)u[l.sessionId]=(u[l.sessionId]||0)+1;const f=new Set(manager.listSessions().map((l=>l.id)));i.json({drafts:s.map((l=>({...l,sessionAlive:f.has(l.sessionId)}))),counts:u})}catch(e){i.status(500).json({error:e.message})}})),app.post("/api/inbox",checkAuth,express.json({limit:"1mb"}),((d,i)=>{const n=getUserInfo(d.headers.cookie),t=d.body||{},e=t.sessionId?manager.get(t.sessionId):null;try{const s=addDraft({...t,owner:t.owner||n?.name||null},e);maybeKickRelay(s),i.json({ok:!0,draft:s})}catch(s){i.status(400).json({error:s.message})}})),app.put("/api/inbox/:id",checkAuth,express.json({limit:"1mb"}),((d,i)=>{const n=d.body||{},t=n.sessionId?manager.get(n.sessionId):null,e=updateDraft(d.params.id,n,t);if(!e)return i.status(404).json({error:"\u8349\u7A3F\u4E0D\u5B58\u5728"});maybeKickRelay(e),i.json({ok:!0,draft:e})})),app.post("/api/inbox/reorder",checkAuth,express.json(),((d,i)=>{const{sessionId:n,ids:t}=d.body||{};if(!n||!Array.isArray(t))return i.status(400).json({error:"\u53C2\u6570\u4E0D\u5BF9"});reorderDrafts(n,t.map(String)),i.json({ok:!0})})),app.post("/api/inbox/merge",checkAuth,express.json(),((d,i)=>{try{const n=mergeDrafts((d.body?.ids||[]).map(String));maybeKickRelay(n),i.json({ok:!0,draft:n})}catch(n){i.status(400).json({error:n.message})}})),app.post("/api/inbox/:id/unmerge",checkAuth,((d,i)=>{try{i.json({ok:!0,drafts:unmergeDraft(d.params.id)})}catch(n){i.status(400).json({error:n.message})}})),app.post("/api/inbox/resume",checkAuth,express.json(),((d,i)=>{const n=manager.get(String(d.body?.sessionId||""));if(!n||typeof n._maybeRelayDraft!="function")return i.status(404).json({error:"\u4EFB\u52A1\u4E0D\u5B58\u5728"});if(n.isBusy)return i.json({ok:!0,busy:!0});n._maybeRelayDraft(),i.json({ok:!0})})),app.delete("/api/inbox/:id",checkAuth,((d,i)=>{if(!removeDraft(d.params.id))return i.status(404).json({error:"\u8349\u7A3F\u4E0D\u5B58\u5728"});i.json({ok:!0})}));function _spawnOpen(d,i,n=process.platform==="win32"){return new Promise((t=>{try{const e=(0,external_child_process_namespaceObject.spawn)(d,i,{detached:!0,stdio:"ignore",shell:n});e.on("error",(s=>{console.warn("[open-folder]",d,"\u5931\u8D25:",s.message),t(!1)})),e.unref(),setTimeout((()=>t(!0)),300)}catch(e){console.warn("[open-folder] spawn \u5F02\u5E38:",e.message),t(!1)}}))}let _winSessionId;process.platform==="win32"&&(0,external_child_process_namespaceObject.execFile)("tasklist",["/FI",`PID eq ${process.pid}`,"/FO","CSV","/NH"],{windowsHide:!0,timeout:5e3},((d,i)=>{const n=!d&&String(i).match(/^"[^"]*","\d+","[^"]*","(\d+)"/m);_winSessionId=n?Number(n[1]):null,_winSessionId===0&&console.log("[open-folder] myhi \u8FD0\u884C\u5728\u540E\u53F0\u4F1A\u8BDD\uFF08Session 0\uFF09\uFF0C\u300C\u6253\u5F00\u6587\u4EF6\u5939\u300D\u5DF2\u505C\u7528")}));function hasDesktop(){return process.platform==="linux"?!!(process.env.DISPLAY||process.env.WAYLAND_DISPLAY):process.platform==="win32"?_winSessionId!==0:!0}const NO_DESKTOP_MSG="myhi \u5F53\u524D\u4EE5\u540E\u53F0\u670D\u52A1\u65B9\u5F0F\u8FD0\u884C\uFF08\u6CA1\u6709\u684C\u9762\uFF09\uFF0C\u65E0\u6CD5\u5728\u672C\u673A\u5F39\u51FA\u6587\u4EF6\u5939\u7A97\u53E3\uFF0C\u8BF7\u7528\u300C\u6587\u4EF6\u300D\u9762\u677F\u6D4F\u89C8/\u4E0B\u8F7D";app.post("/api/session/:id/open-folder",checkAuth,(async(d,i)=>{const n=manager.get(d.params.id);if(!n?.cwd)return i.status(404).json({error:"\u4F1A\u8BDD\u6216\u76EE\u5F55\u4E0D\u5B58\u5728"});if(!(0,external_fs_.existsSync)(n.cwd))return i.status(400).json({error:"\u76EE\u5F55\u4E0D\u5B58\u5728\uFF08\u53EF\u80FD\u88AB\u79FB\u52A8/\u5220\u9664\uFF09: "+n.cwd});if(!hasDesktop())return i.json({ok:!1,cwd:n.cwd,error:NO_DESKTOP_MSG});let t=n.cwd;if(process.platform==="win32"){t=t.replace(/\//g,"\\").replace(/(?<!^[A-Za-z]:)\\+$/,"");let s=await _spawnOpen("explorer.exe",[t],!1);s||(s=await _spawnOpen("cmd.exe",["/c","start","",t]));const u=t.split("\\").filter(Boolean).pop()||"";if(u){const f=`$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",f],!1)}return console.log("[open-folder]",t,s?"\u5DF2\u62C9\u8D77":"\u5931\u8D25"),i.json({ok:s,cwd:t})}const e=process.platform==="darwin"?await _spawnOpen("open",[t]):await _spawnOpen("xdg-open",[t]);i.json({ok:e,cwd:t})}));function getPkgVersion(){for(const d of["../package.json","./package.json","package.json"])try{const i=JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(server_dirname,d),"utf8")).version;if(i&&i!=="0.0.0")return i}catch{}return"0.0.0"}const PKG_VERSION=getPkgVersion();let _latestVersion=null,_lastVersionCheck=0;const VERSION_CHECK_INTERVAL=600*1e3;async function checkLatestVersion(){const d=Date.now();if(_latestVersion&&d-_lastVersionCheck<VERSION_CHECK_INTERVAL)return _latestVersion;const i=await latestVersion("@wendongfly/myhi",npmRegistryPref());return i&&(_latestVersion=i.version,_lastVersionCheck=d),_latestVersion}function npmRegistryPref(){return _configString("npmRegistry")||"auto"}function semverGt(d,i){const n=String(d||"").split(/[.-]/).map(Number),t=String(i||"").split(/[.-]/).map(Number);for(let e=0;e<3;e++){const s=n[e]||0,u=t[e]||0;if(s!==u)return s>u}return!1}app.get("/api/version",(async(d,i)=>{const n=PKG_VERSION,t=await checkLatestVersion();i.json({current:n,latest:t||n,updateAvailable:!!t&&semverGt(t,n),upgrade:upgradeState()})}));function isSystemd(){return process.platform==="linux"&&process.ppid===1&&!!(process.env.INVOCATION_ID||process.env.JOURNAL_STREAM)}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{try{const d=[PKG_ROOT,"bin","daemon.js"].join(external_path_.sep),i=(0,external_fs_.openSync)((0,external_path_.join)(server_configDir,"daemon.log"),"a");(0,external_child_process_namespaceObject.spawn)(process.execPath,[d,...process.argv.slice(2)],{detached:!0,stdio:["ignore",i,i],windowsHide:!0,env:{...process.env,MYHI_WAIT_PID:String(process.pid)}}).unref(),console.log("[myhi] \u5DF2\u8F6C\u4E3A\u540E\u53F0\u8FD0\u884C\uFF08daemon\uFF09\uFF0C\u67E5\u770B\u65E5\u5FD7\uFF1Amyhi log")}catch(d){console.error("[myhi] \u62C9\u8D77 daemon \u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u91CD\u65B0\u8FD0\u884C myhi\uFF1A",d.message)}gracefulShutdown(),setTimeout((()=>process.exit(0)),300)}}app.get("/api/server-config",adminBearerOr(checkAuth),((d,i)=>{const n=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""}})();i.json({asrUrl:n||""})}));function requireAdmin(d,i,n){const t=getUserInfo(d.headers.cookie);if(t&&t.role!=="admin")return i.status(403).json({ok:!1,error:"\u4EC5\u7BA1\u7406\u5458\u53EF\u6267\u884C\u6B64\u64CD\u4F5C"});n()}const prefsFile=(0,external_path_.join)(server_configDir,"prefs.json"),PREF_KEYS=new Set(["theme","font","chat"]);function prefsKey(d){const i=getUserInfo(d.headers.cookie);return i&&i.role!=="admin"?"u:"+i.name:"admin"}function loadAllPrefs(){try{return JSON.parse((0,external_fs_.readFileSync)(prefsFile,"utf8").replace(/^\uFEFF/,""))||{}}catch{return{}}}app.get("/api/prefs",checkAuth,((d,i)=>i.json({ok:!0,prefs:loadAllPrefs()[prefsKey(d)]||null}))),app.put("/api/prefs",checkAuth,express.json({limit:"16kb"}),((d,i)=>{const n=d.body||{},t={};for(const[u,f]of Object.entries(n))PREF_KEYS.has(u)&&(t[u]=f);if(JSON.stringify(t).length>8192)return i.status(413).json({ok:!1,error:"\u504F\u597D\u6570\u636E\u8FC7\u5927"});const e=loadAllPrefs(),s=prefsKey(d);e[s]={...e[s]||{},...t,updatedAt:Date.now()};try{(0,external_fs_.writeFileSync)(prefsFile,JSON.stringify(e,null,2))}catch(u){return i.status(500).json({ok:!1,error:u.message})}i.json({ok:!0,updatedAt:e[s].updatedAt})})),app.post("/api/server-config",adminBearerOr(checkAuth,requireAdmin),express.json(),((d,i)=>{const{asrUrl:n}=d.body||{},t=(0,external_path_.join)((0,external_os_.homedir)(),".myhi","asr.json");try{const e=(n||"").trim();(0,external_fs_.writeFileSync)(t,JSON.stringify({url:e},null,2),"utf8"),i.json({ok:!0})}catch(e){i.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",adminBearerOr(checkAuth),((d,i)=>{i.json({name:machineName(),hostname:shortHostname(),fromEnv:!!process.env.MYHI_NAME})})),app.post("/api/machine-name",adminBearerOr(checkAuth,requireAdmin),express.json(),((d,i)=>{const n=String(d.body?.name??"").trim().slice(0,32),t=(0,external_path_.join)(server_configDir,"config.json");try{const e=_readConfig();n?e.name=n:delete e.name,(0,external_fs_.writeFileSync)(t,JSON.stringify(e,null,2),"utf8"),i.json({ok:!0,name:machineName()})}catch(e){i.status(500).json({error:e.message})}})),app.get("/api/models",checkAuth,(async(d,i)=>{const n=await listGatewayModels({force:d.query.refresh==="1"});i.json({ok:!0,...n,scenes:readSceneModels(),sceneLabels:SCENES})})),app.post("/api/model-scenes",adminBearerOr(checkAuth,requireAdmin),express.json(),((d,i)=>{const n=d.body||{};try{const t=_readConfig(),e={};for(const s of Object.keys(SCENES)){const u=String(n[s]??"").trim();if(u.length>120||/\s/.test(u))return i.status(400).json({ok:!1,error:`\u300C${SCENES[s]}\u300D\u7684\u6A21\u578B\u540D\u4E0D\u5BF9\uFF1A${u}`});u&&(e[s]=u)}t.models=e,("ask"in e||n.ask==="")&&delete t.askModel,(0,external_fs_.writeFileSync)((0,external_path_.join)(server_configDir,"config.json"),JSON.stringify(t,null,2),"utf8"),console.log("[myhi] \u573A\u666F\u6A21\u578B\u5DF2\u66F4\u65B0:",JSON.stringify(e)),i.json({ok:!0,scenes:readSceneModels()})}catch(t){i.status(500).json({ok:!1,error:"\u5199\u914D\u7F6E\u5931\u8D25\uFF1A"+t.message})}})),app.get("/api/server-mode",checkAuth,((d,i)=>{i.json({ok:!0,httpOnly:!_tlsOpts,fromEnv:!!process.env.MYHI_NO_HTTPS,port:PORT,configDir:server_configDir})})),app.post("/api/server-mode",adminBearerOr(checkAuth,requireAdmin),express.json(),((d,i)=>{const n=!!d.body?.httpOnly;if(process.env.MYHI_NO_HTTPS&&!n)return i.status(400).json({ok:!1,error:"\u542F\u52A8\u53C2\u6570\u91CC\u8BBE\u4E86\u73AF\u5883\u53D8\u91CF MYHI_NO_HTTPS\uFF0C\u5F3A\u5236 HTTP\uFF1B\u8981\u5207\u56DE HTTPS \u9700\u5148\u53BB\u6389\u5B83"});try{const t=_readConfig();t.httpOnly=n,(0,external_fs_.writeFileSync)((0,external_path_.join)(server_configDir,"config.json"),JSON.stringify(t,null,2),"utf8")}catch(t){return i.status(500).json({ok:!1,error:"\u5199\u914D\u7F6E\u5931\u8D25\uFF1A"+t.message})}console.log(`[myhi] \u7F51\u9875\u5207\u6362\u8BBF\u95EE\u534F\u8BAE \u2192 ${n?"HTTP":"HTTPS"}\uFF0C\u91CD\u542F\u751F\u6548\uFF08\u914D\u7F6E ${(0,external_path_.join)(server_configDir,"config.json")}\uFF09`),i.json({ok:!0,httpOnly:n,port:PORT}),setTimeout((()=>restartService()),500)})),app.get("/api/npm-registry",checkAuth,((d,i)=>{i.json({ok:!0,pref:npmRegistryPref()})})),app.post("/api/npm-registry",adminBearerOr(checkAuth,requireAdmin),express.json(),((d,i)=>{const n=String(d.body?.pref||"auto");if(!["auto","official","mirror"].includes(n))return i.status(400).json({ok:!1,error:"\u53EA\u80FD\u9009 auto / official / mirror"});try{const t=_readConfig();n==="auto"?delete t.npmRegistry:t.npmRegistry=n,(0,external_fs_.writeFileSync)((0,external_path_.join)(server_configDir,"config.json"),JSON.stringify(t,null,2),"utf8")}catch(t){return i.status(500).json({ok:!1,error:"\u5199\u914D\u7F6E\u5931\u8D25\uFF1A"+t.message})}_latestVersion=null,_latestClaude=null,i.json({ok:!0,pref:n})})),app.post("/api/restart",checkAuth,((d,i)=>{i.json({ok:!0}),setTimeout((()=>restartService()),300)}));const PKG_ROOT=(0,external_path_.join)(server_dirname,".."),DAEMON_CAPS=(process.env.MYHI_DAEMON_CAPS||"").split(",");let _upgrade={running:!1};function readLastUpgrade(){try{return JSON.parse((0,external_fs_.readFileSync)(upgradeStatusFile(server_configDir),"utf8"))}catch{return null}}function upgradeState(){if(_upgrade.running)return{running:!0,startedAt:_upgrade.startedAt,target:_upgrade.target};const d=_upgrade.result||readLastUpgrade();return d&&Date.now()-(d.at||0)<1800*1e3?{running:!1,last:d}:{running:!1}}function busyAgentTitles(){try{return manager.listSessions().filter((d=>d.mode==="agent"&&d.isBusy)).map((d=>d.title||d.id))}catch{return[]}}function recordUpgrade(d){d.at=Date.now(),_upgrade={running:!1,result:d};try{(0,external_fs_.writeFileSync)(upgradeStatusFile(server_configDir),JSON.stringify(d,null,2))}catch{}console.log(d.ok?`[myhi] \u5347\u7EA7\u6210\u529F\uFF1A${d.from} \u2192 ${d.to}`:`[myhi] \u5347\u7EA7\u5931\u8D25\uFF1A${d.error}`)}async function handleUpgrade(d,i){if(_upgrade.running)return i.status(409).json({ok:!1,error:"\u5347\u7EA7\u5DF2\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7A0D\u5019"});const n=busyAgentTitles();if(n.length&&!d.body?.force)return i.status(409).json({ok:!1,busy:n,error:`\u6709 ${n.length} \u4E2A\u4EFB\u52A1\u6B63\u5728\u6267\u884C\uFF1A${n.join("\u3001")}\u3002\u5347\u7EA7\u4F1A\u91CD\u542F\u670D\u52A1\u3001\u6253\u65AD\u5B83\u4EEC\u8FD9\u4E00\u8F6E\u3002`});const t=PKG_VERSION,{candidates:e,note:s}=await upgradeCandidates("@wendongfly/myhi",t,npmRegistryPref());if(!e.length)return i.json({ok:!1,error:s});const u=e[0].version;if(process.platform==="win32"&&process.send&&DAEMON_CAPS.includes("upgrade-v2")){_upgrade={running:!0,startedAt:Date.now(),target:u},i.json({ok:!0,mode:"daemon",from:t,target:u,message:"\u6B63\u5728\u505C\u6B62\u670D\u52A1\u5E76\u5B89\u88C5\u65B0\u7248\u672C\uFF0C\u7EA6 1~3 \u5206\u949F\uFF0C\u671F\u95F4\u9875\u9762\u4F1A\u65AD\u5F00\u2026"}),setTimeout((()=>process.send({type:"upgrade",target:u,candidates:e})),300);return}_upgrade={running:!0,startedAt:Date.now(),target:u},i.json({ok:!0,mode:"server",from:t,target:u,message:"\u6B63\u5728\u4E0B\u8F7D\u5B89\u88C5\u65B0\u7248\u672C\u2026"});const f=[];let l=null;for(const o of e){try{if(console.log(`[myhi] \u5347\u7EA7\uFF1A\u4ECE${registryName(o.registry)}\u5B89\u88C5 ${o.version}`),await execAsync(npmUpgradeCmd(PKG_ROOT,o.registry),{encoding:"utf8",timeout:6e5,windowsHide:!0}),l=checkInstall(PKG_ROOT,o.version),l.ok)break;f.push(`${registryName(o.registry)}\uFF1A${l.error}`)}catch(c){const r=(c.stderr||c.stdout||c.message||"").split(`
|
|
439
|
+
`)[0]}catch{}try{if(process.platform==="win32"){const d=(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(d)return d[1]}else try{const d=(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(d)return d[1]}catch{const d=(0,external_child_process_namespaceObject.execSync)("route -n get default 2>/dev/null || route -n 2>/dev/null",{timeout:3e3,stdio:"pipe"}).toString(),i=d.match(/interface:\s*(\S+)/i)||d.match(/0\.0\.0\.0\s+(\d+\.\d+\.\d+\.\d+)/);if(i){const n=(0,external_os_.networkInterfaces)()[i[1]];if(n){const t=n.find((e=>e.family==="IPv4"&&!e.internal));if(t)return t.address}if(/^\d+\.\d+\.\d+\.\d+$/.test(i[1]))return i[1]}}}catch{}for(const d of Object.values((0,external_os_.networkInterfaces)()))for(const i of d)if(i.family==="IPv4"&&!i.internal)return i.address;return"localhost"}function parseCookies(d=""){const i={};for(const n of d.split(";")){const t=n.indexOf("=");t>0&&(i[n.slice(0,t).trim()]=n.slice(t+1).trim())}return i}const SESSION_COOKIE="myhi_sid",SESSION_COOKIE_HTTP="myhi_sid_h",COOKIE_OPTS_BASE="HttpOnly; SameSite=Strict; Path=/; Max-Age=31536000",isSecureReq=d=>!!(d?.secure||d?.headers?.["x-forwarded-proto"]==="https");function cookieOpts(d){return isSecureReq(d)?COOKIE_OPTS_BASE+"; Secure":COOKIE_OPTS_BASE}function setSessionCookie(d,i,n){d.setHeader("Set-Cookie",`${isSecureReq(n)?SESSION_COOKIE:SESSION_COOKIE_HTTP}=${i||TOKEN}; ${cookieOpts(n)}`)}const CLEAR_SESSION_COOKIES=[SESSION_COOKIE,SESSION_COOKIE_HTTP].map((d=>`${d}=; HttpOnly; SameSite=Strict; Path=/; Max-Age=0`));function getSessionToken(d){const i=parseCookies(d),n=[i[SESSION_COOKIE],i[SESSION_COOKIE_HTTP]].filter(Boolean);return n.find((t=>userSessions.has(t)))||n[0]||null}function hasValidSession(d){const i=getSessionToken(d);if(i&&userSessions.has(i)){const n=userSessions.get(i);return n&&(n.lastUsed=Date.now()),!0}return!1}function getUserInfo(d){const i=getSessionToken(d);return i?userSessions.get(i):null}const app=express();app.set("trust proxy",!0),app.use(((d,i,n)=>{i.setHeader("Referrer-Policy","no-referrer"),i.setHeader("X-Content-Type-Options","nosniff"),n()}));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(d){const i=_readConfig()[d];return typeof i=="string"&&i?i: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)(((d,i)=>{const n=(d.headers.host||"").replace(/:\d+$/,"");i.writeHead(301,{Location:`https://${n}:${PORT}${d.url}`}),i.end()}))):(process.env.MYHI_NO_HTTPS||_readConfig().httpOnly?console.log("[myhi] \u6309\u8BBE\u7F6E\u4EE5 HTTP \u6A21\u5F0F\u8FD0\u884C\uFF08\u624B\u673A\u7B49\u975E\u672C\u673A\u6D4F\u89C8\u5668\u4E0D\u80FD\u7528\u9EA6\u514B\u98CE / \u6444\u50CF\u5934\uFF09\uFF1B\u5207\u56DE HTTPS\uFF1A\u7F51\u9875 \u8BBE\u7F6E \u203A \u670D\u52A1 \u203A \u8BBF\u95EE\u534F\u8BAE\uFF0C\u6216 myhi --https"):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 d of[httpsServer,httpServer])d&&(d.keepAliveTimeout=72e3,d.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({perMessageDeflate:{threshold:1024},serveClient:!1,cors:{origin:(d,i)=>{if(!d||_corsAllowed.test(d))return i(null,!0);i(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(d,i){if(!AUTO_ATTACH||_autoSpawned.has(d)||!process.env.DISPLAY&&process.platform==="linux")return;_autoSpawned.add(d);const n=(0,external_path_.join)(server_dirname,"attach.js"),t=process.execPath,e=i||"myhi";if(process.platform==="win32"){const s=`"${t}" "${n}" ${d}`,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",(f=>{console.warn("[attach] wt.exe \u5931\u8D25\uFF0C\u56DE\u9000\u5230 cmd:",f.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 "${t} ${n} ${d}"`;(0,external_child_process_namespaceObject.spawn)("osascript",["-e",s],{detached:!0,stdio:"ignore"}).unref()}else{const s=`${t} "${n}" ${d}`;for(const[u,f]of[["gnome-terminal",["--","bash","-c",`${s}; exec bash`]],["xterm",["-title",e,"-e",s]],["konsole",["--new-tab","-e",s]]]){const l=(0,external_child_process_namespaceObject.spawn)(u,f,{detached:!0,stdio:"ignore"});l.unref(),l.on("error",(()=>{}));break}}}const uploadDir=(0,external_path_.join)(server_configDir,"uploads");(0,external_fs_.mkdirSync)(uploadDir,{recursive:!0});function checkAuth(d,i,n){const t=d.query.token;if(t&&(t===TOKEN||userSessions.has(t))){const e=userSessions.get(t);if(e?.onetime){userSessions.delete(t);const f=(0,external_crypto_.randomBytes)(16).toString("hex");userSessions.set(f,{role:e.role,name:e.name,lastUsed:Date.now()}),setSessionCookie(i,f,d)}else setSessionCookie(i,t===TOKEN?TOKEN:t,d);const s=Object.keys(d.query).filter((f=>f!=="token")),u=d.path+(s.length?"?"+new URLSearchParams(Object.fromEntries(Object.entries(d.query).filter((([f])=>f!=="token")))):"");return i.redirect(u)}if(hasValidSession(d.headers.cookie)){if(isExclusiveMode()&&activeUser){const e=getSessionToken(d.headers.cookie);if(e!==TOKEN){const s=userSessions.get(e);if(!s||s.name!==activeUser.name)return i.setHeader("Set-Cookie",CLEAR_SESSION_COOKIES),i.redirect("/login")}}return n()}i.redirect("/login")}const _require=(0,external_module_namespaceObject.createRequire)(import.meta.url);function pkgDirSafe(d){try{return(0,external_path_.dirname)(_require.resolve(`${d}/package.json`))}catch{return null}}const libDir=(0,external_path_.join)(server_dirname,"lib"),staticOpts={maxAge:864e5};app.get("/theme.js",((d,i)=>{const n=_configString("defaultTheme");i.setHeader("Content-Type","application/javascript; charset=utf-8"),i.setHeader("Cache-Control","no-cache"),i.send(`window.MYHI_DEFAULT_THEME=${JSON.stringify(["light","dark","black","system"].includes(n)?n:"dark")};`)})),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:(d,i)=>{i.endsWith(".js")&&d.setHeader("Content-Type","application/javascript; charset=utf-8")}})),app.get("/manifest.json",((d,i)=>i.sendFile((0,external_path_.join)(server_dirname,"manifest.json")))),app.get("/icon.png",((d,i)=>i.sendFile((0,external_path_.join)(server_dirname,"icon.png")))),app.get("/icon.svg",((d,i)=>i.sendFile((0,external_path_.join)(server_dirname,"icon.svg"))));const _loginAttempts=new Map,LOGIN_MAX_ATTEMPTS=5,LOGIN_LOCKOUT_MS=300*1e3;function checkLoginRate(d){const i=Date.now(),n=_loginAttempts.get(d);return!n||i>n.resetAt?!0:n.count<LOGIN_MAX_ATTEMPTS}function recordLoginFailure(d){const i=Date.now(),n=_loginAttempts.get(d);!n||i>n.resetAt?_loginAttempts.set(d,{count:1,resetAt:i+LOGIN_LOCKOUT_MS}):n.count++}function clearLoginFailures(d){_loginAttempts.delete(d)}setInterval((()=>{const d=Date.now();for(const[i,n]of _loginAttempts)d>n.resetAt&&_loginAttempts.delete(i)}),600*1e3),app.get("/login",((d,i)=>{sendPage(d,i,"login.html")})),app.post("/login",express.urlencoded({extended:!1}),((d,i)=>{const n=d.ip;if(!checkLoginRate(n))return i.redirect("/login?error=locked");loadRoles(),loadUsers();const t=d.body?.password,e=d.query.from,s=e&&e.startsWith("/")&&!e.startsWith("//")?e:"/",u=hasUsers()?lookupUser(t):null;if(u){if(isExclusiveMode()&&activeUser&&activeUser.name!==u.name)return i.redirect("/login?error=occupied&user="+encodeURIComponent(activeUser.name));clearLoginFailures(n);const l=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(l,{role:memberRole(),member:!0,name:u.name,dir:u.dir,lastUsed:Date.now()}),isExclusiveMode()&&(activeUser?activeUser.tokens.add(l):activeUser={name:u.name,dir:u.dir,tokens:new Set([l]),loginAt:Date.now()}),setSessionCookie(i,l,d),console.log(`[\u767B\u5F55] ${u.name} \u767B\u5F55\uFF08${isMultiUser()?isExclusiveMode()?"\u72EC\u5360":"\u5171\u4EAB":"\u5355\u7528\u6237"}\u6A21\u5F0F\uFF09`),i.redirect(s)}const f=lookupPassword(t);if(f){clearLoginFailures(n);const l=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(l,{role:f.role,name:f.name,lastUsed:Date.now()}),setSessionCookie(i,l,d),i.redirect(s)}if(t===PASSWORD){clearLoginFailures(n);const l=(0,external_crypto_.randomBytes)(16).toString("hex");return userSessions.set(l,{role:"admin",name:"\u7BA1\u7406\u5458",lastUsed:Date.now()}),setSessionCookie(i,l,d),i.redirect(s)}recordLoginFailure(n),i.redirect("/login?error=1")})),app.post("/logout",((d,i)=>{const n=getSessionToken(d.headers.cookie);n&&(activeUser&&activeUser.tokens.has(n)&&(activeUser.tokens.delete(n),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(n)),i.setHeader("Set-Cookie",CLEAR_SESSION_COOKIES),i.redirect("/login")})),app.get("/api/status",((d,i)=>{if(isExclusiveMode()&&activeUser)return i.json({occupied:!0,userName:activeUser.name,releasing:!!_exclusiveReleaseTimer});if(isMultiUser()&&!isExclusiveMode()){const n=new Set;for(const[,t]of io.sockets.sockets){if(!t.data.userName||t.data.userName==="\u7BA1\u7406\u5458")continue;const e=t.handshake.headers.cookie;e&&!hasValidSession(e)||n.add(t.data.userName)}return i.json({occupied:!1,onlineUsers:[...n]})}i.json({occupied:!1})}));const _gzFresh=new Map;function gzFresh(d){try{const i=(0,external_fs_.statSync)(d),n=i.size+":"+i.mtimeMs,t=_gzFresh.get(d);if(t&&t.key===n)return t.ok;const e=(0,external_fs_.openSync)(d+".gz","r"),s=Buffer.alloc(4);try{(0,external_fs_.readSync)(e,s,0,4,(0,external_fs_.fstatSync)(e).size-4)}finally{(0,external_fs_.closeSync)(e)}const u=s.readUInt32LE(0)===i.size>>>0;return _gzFresh.set(d,{key:n,ok:u}),u}catch{return!1}}function sendPage(d,i,n){const t=(0,external_path_.join)(server_dirname,n);if(gzFresh(t)&&/\bgzip\b/.test(d.headers["accept-encoding"]||""))return i.setHeader("Content-Type","text/html; charset=UTF-8"),i.setHeader("Content-Encoding","gzip"),i.setHeader("Vary","Accept-Encoding"),i.sendFile(t+".gz");i.sendFile(t)}app.get("/admin",((d,i)=>sendPage(d,i,"admin.html"))),app.get("/",checkAuth,((d,i)=>sendPage(d,i,"index.html"))),app.get("/terminal/:id",checkAuth,((d,i)=>sendPage(d,i,"chat.html"))),app.get("/grid",checkAuth,((d,i)=>sendPage(d,i,"grid.html"))),app.get("/terminal-raw/:id",checkAuth,((d,i)=>sendPage(d,i,"terminal.html"))),app.use("/lib",express.static((0,external_path_.join)(server_dirname,"lib"),{maxAge:0,setHeaders:d=>d.setHeader("Cache-Control","no-cache")}));const migrateTmp=(0,external_path_.join)(server_configDir,"migrate-tmp"),_migrateUploads=new Map;try{(0,external_fs_.rmSync)(migrateTmp,{recursive:!0,force:!0})}catch{}setInterval((()=>{for(const[d,i]of _migrateUploads)if(Date.now()-i.at>36e5){try{(0,external_fs_.rmSync)(i.file,{force:!0})}catch{}_migrateUploads.delete(d)}}),6e5).unref();function migrateSess(d,i){const n=getUserInfo(d.headers.cookie),t=manager.get(d.params.id);return!t||t.mode!=="agent"?(i.status(404).json({ok:!1,error:"\u4EFB\u52A1\u4E0D\u5B58\u5728"}),null):n&&n.role!=="admin"&&t.owner&&t.owner!==n.name?(i.status(403).json({ok:!1,error:"\u4E0D\u80FD\u5BFC\u51FA\u522B\u4EBA\u7684\u4EFB\u52A1"}),null):t}app.get("/api/migrate/:id/preview",checkAuth,((d,i)=>{const n=migrateSess(d,i);n&&i.json({ok:!0,...exportPreview(n),excludeDirs:EXCLUDE_DIRS})})),app.get("/api/migrate/:id/export",checkAuth,(async(d,i)=>{const n=migrateSess(d,i);if(!n)return;const t=new Date,e=`${t.getFullYear()}${String(t.getMonth()+1).padStart(2,"0")}${String(t.getDate()).padStart(2,"0")}`,s=`${String(n.title||"task").replace(/[\\/:*?"<>|]+/g,"_").slice(0,60)}-${e}${PACK_EXT}`;i.setHeader("Content-Type","application/gzip"),i.setHeader("Content-Disposition",`attachment; filename="myhi-task${PACK_EXT}"; filename*=UTF-8''${encodeURIComponent(s)}`);try{await exportTask(n,{conv:d.query.conv!=="0",mem:d.query.mem!=="0",from:machineName()},i)}catch(u){console.error("[\u8FC1\u79FB] \u5BFC\u51FA\u5931\u8D25:",u.message),i.destroy(u)}console.log(`[\u8FC1\u79FB] \u5BFC\u51FA\u4EFB\u52A1\u300C${n.title}\u300D(${n.id}) conv=${d.query.conv!=="0"} mem=${d.query.mem!=="0"}`)})),app.post("/api/migrate/upload",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie);if(n&&!hasPermission(n.role,"operator"))return i.status(403).json({ok:!1,error:"\u4F60\u7684\u89D2\u8272\u4E0D\u80FD\u5BFC\u5165\u4EFB\u52A1"});(0,external_fs_.mkdirSync)(migrateTmp,{recursive:!0}),multer({dest:migrateTmp,limits:{fileSize:8*1024**3}}).single("pack")(d,i,(async t=>{if(t)return i.status(400).json({ok:!1,error:t.message});if(!d.file)return i.status(400).json({ok:!1,error:"\u6CA1\u6709\u6536\u5230\u6587\u4EF6"});try{const e=await readManifest(d.file.path),s=(0,external_crypto_.randomBytes)(12).toString("hex");_migrateUploads.set(s,{file:d.file.path,user:n?.name||null,at:Date.now()}),i.json({ok:!0,token:s,manifest:e,userDir:n?.dir||null})}catch(e){try{(0,external_fs_.rmSync)(d.file.path,{force:!0})}catch{}i.status(400).json({ok:!1,error:/incorrect header|unexpected end|invalid/i.test(e.message)?"\u6587\u4EF6\u4E0D\u662F\u6709\u6548\u7684 myhi \u8FC1\u79FB\u5305\uFF08\u53EF\u80FD\u4E0B\u8F7D\u4E0D\u5B8C\u6574\u6216\u4E0D\u662F .myhipack\uFF09":e.message})}}))})),app.post("/api/migrate/import",checkAuth,express.json(),(async(d,i)=>{const n=getUserInfo(d.headers.cookie),t=_migrateUploads.get(String(d.body?.token||""));if(!t||t.user&&t.user!==(n?.name||null))return i.status(400).json({ok:!1,error:"\u4E0A\u4F20\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8FC1\u79FB\u5305"});const e=String(d.body?.cwd||"").trim();if(!e||!(0,external_path_.isAbsolute)(e))return i.status(400).json({ok:!1,error:"\u8BF7\u586B\u5199\u5B8C\u6574\u7684\u76EE\u6807\u76EE\u5F55\uFF08\u7EDD\u5BF9\u8DEF\u5F84\uFF09"});const s=(0,external_path_.resolve)((0,external_path_.normalize)(e));if(n?.dir){const u=(0,external_path_.resolve)((0,external_path_.normalize)(n.dir));if(s!==u&&!s.startsWith(u+external_path_.sep))return i.status(403).json({ok:!1,error:`\u53EA\u80FD\u5BFC\u5165\u5230\u4F60\u7684\u76EE\u5F55 ${u} \u91CC`})}try{if((0,external_fs_.existsSync)(s)&&(0,external_fs_.readdirSync)(s).length)return i.status(409).json({ok:!1,error:"\u76EE\u6807\u76EE\u5F55\u5DF2\u5B58\u5728\u4E14\u4E0D\u662F\u7A7A\u7684\u3002\u6362\u4E00\u4E2A\u76EE\u5F55\u540D\uFF0C\u907F\u514D\u8986\u76D6\u5DF2\u6709\u6587\u4EF6"})}catch{}try{const{manifest:u,sid:f,memory:l}=await importPack(t.file,s),o=manager.createAgent({title:u.title||"\u8FC1\u79FB\u7684\u4EFB\u52A1",cwd:s,tags:u.tags||[],firstUserText:u.firstUserText||"",resumeSessionId:f||void 0,owner:n?.name,userDir:n?.dir});broadcastSessions();try{(0,external_fs_.rmSync)(t.file,{force:!0})}catch{}_migrateUploads.delete(String(d.body.token)),console.log(`[\u8FC1\u79FB] \u5BFC\u5165\u4EFB\u52A1\u300C${u.title}\u300D\u2192 ${s}\uFF08\u6765\u81EA ${u.from||"?"}\uFF0C\u5BF9\u8BDD=${!!f}\uFF09`),i.json({ok:!0,id:o.id,conv:!!f,memory:l,secrets:u.secrets||[]})}catch(u){console.error("[\u8FC1\u79FB] \u5BFC\u5165\u5931\u8D25:",u.message),i.status(500).json({ok:!1,error:"\u5BFC\u5165\u5931\u8D25\uFF1A"+u.message})}})),app.get("/api/sessions",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie);i.json(manager.list(n?.name,n?.role==="admin"))})),app.get("/api/usage",((d,i)=>{try{const n=manager.listSessions().filter((e=>e.mode==="agent"&&e.alive)).map((e=>({id:e.id,title:e.title,owner:e.owner,usage:e._usage})));let t=null;for(const e of n)if(e.usage?.rateLimitInfo){t=e.usage.rateLimitInfo;break}i.json({rateLimit:t,activeSessions:n})}catch(n){i.status(500).json({error:n.message})}})),app.post("/api/sessions",checkAuth,express.json(),((d,i)=>{const n=getUserInfo(d.headers.cookie),t=manager.create({...d.body,owner:n?.name,userDir:n?.dir});i.status(201).json(t.toJSON())})),app.delete("/api/sessions/:id",checkAuth,((d,i)=>{manager.kill(d.params.id),i.status(204).end()})),app.get("/api/sessions/health",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie),t=manager.listSessions().filter((e=>e.mode==="agent")).filter((e=>!e.owner||!n?.name||e.owner===n.name)).map((e=>({...e.toJSON(),health:getSessionHealth(e.claudeSessionId)})));i.json({ok:!0,sessions:t})})),app.post("/api/sessions/:id/reset",checkAuth,((d,i)=>{const n=manager.get(d.params.id);if(!n||n.mode!=="agent"||typeof n.reset!="function")return i.status(404).json({ok:!1,error:"agent \u4F1A\u8BDD\u4E0D\u5B58\u5728"});n.reset(),console.log(`[reset] \u4F1A\u8BDD ${n.id}\u300C${n.title||""}\u300D\u88AB\u91CD\u5F00\u4E3A\u5E72\u51C0\u4F1A\u8BDD\uFF08\u4F1A\u8BDD\u4F53\u68C0\uFF0Cby ${getUserInfo(d.headers.cookie)?.name||"\u7BA1\u7406\u5458"}\uFF09`),n.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(),i.json({ok:!0})})),app.get("/api/claude-sessions",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie);i.json(listLocalClaudeSessions(n?.dir))}));function sendJsonMaybeGz(d,i,n){const t=Buffer.from(JSON.stringify(n));if(i.setHeader("Content-Type","application/json; charset=utf-8"),i.setHeader("Vary","Accept-Encoding"),t.length>4096&&/\bgzip\b/.test(d.headers["accept-encoding"]||""))return i.setHeader("Content-Encoding","gzip"),i.end((0,external_zlib_.gzipSync)(t));i.end(t)}app.get("/api/agent/history/:sessionId",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n||n.mode!=="agent")return i.status(404).json({ok:!1,error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=n.claudeSessionId;if(!t)return i.json({ok:!0,messages:[],total:0,hasMore:!1});const e=Math.max(0,parseInt(d.query.offset,10)||0),s=Math.min(200,Math.max(1,parseInt(d.query.limit,10)||50)),u=readTranscript(t,{offset:e,limit:s});sendJsonMaybeGz(d,i,{ok:!0,messages:u.messages,total:u.total,hasMore:u.hasMore})})),app.get("/api/dirs",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie);if(!n||n.role!=="admin")return i.status(403).json({error:"\u6CA1\u6709\u76EE\u5F55\u6D4F\u89C8\u6743\u9650"});const t=n.dir?(0,external_path_.resolve)((0,external_path_.normalize)(n.dir)):null,e=process.platform==="win32"?"\\":"/";let s=d.query.path||t||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+="\\"),t&&!u.startsWith(t)&&(u=t);try{const f=(0,external_fs_.readdirSync)(u,{withFileTypes:!0}).filter((c=>c.isDirectory()&&c.name!==".git")).map((c=>({name:c.name,path:u.replace(/[/\\]+$/,"")+e+c.name}))).sort(((c,r)=>c.name.localeCompare(r.name))),l=(0,external_path_.join)(u,".."),o=!t||(0,external_path_.resolve)((0,external_path_.normalize)(l)).startsWith(t);i.json({current:u,parent:o&&l!==u?l:null,dirs:f,drives:process.platform==="win32"&&!t?"CDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((c=>c+":\\")).filter((c=>{try{return(0,external_fs_.existsSync)(c)}catch{return!1}})):[]})}catch(f){i.status(400).json({error:f.message})}}));function safePath(d,i){const n=(0,external_path_.resolve)((0,external_path_.normalize)(d)),t=(0,external_path_.resolve)((0,external_path_.normalize)((0,external_path_.join)(d,i||"")));if(t!==n&&!t.startsWith(n+external_path_.sep))return null;try{const e=(0,external_fs_.realpathSync)(n),s=(0,external_fs_.existsSync)(t)?(0,external_fs_.realpathSync)(t):t;if(s!==e&&!s.startsWith(e+external_path_.sep))return null}catch{}return t}function server_walkFiles(d,i,n=[],t=0,e=[],s=!1,u=1/0){if(t>20||n.length>=u)return n;let f;try{f=(0,external_fs_.readdirSync)(d,{withFileTypes:!0})}catch{return n}for(const l of f){if(l.name===".git"||e.includes(l.name))continue;if(n.length>=u)return n;const o=(0,external_path_.join)(d,l.name),c=i?i+"/"+l.name:l.name;try{const r=(0,external_fs_.lstatSync)(o);if(r.isSymbolicLink())continue;r.isDirectory()?(s&&n.push({name:c,dir:!0,mtime:r.mtimeMs}),server_walkFiles(o,c,n,t+1,e,s,u)):r.isFile()&&n.push({name:c,size:r.size,mtime:r.mtimeMs})}catch{}}return n}function fileHash(d){return new Promise(((i,n)=>{const t=(0,external_crypto_.createHash)("sha256"),e=(0,external_fs_.createReadStream)(d);e.on("data",(s=>t.update(s))),e.on("end",(()=>i(t.digest("hex")))),e.on("error",n)}))}app.get("/api/files/:sessionId",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=d.query.path||"",e=safePath(n.cwd,t);if(!e)return i.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});try{if(!(0,external_fs_.statSync)(e).isDirectory())return i.status(400).json({error:"\u4E0D\u662F\u76EE\u5F55"});const s=(0,external_fs_.readdirSync)(e,{withFileTypes:!0}).filter((l=>l.name!==".git")).map((l=>{const o=(0,external_path_.join)(e,l.name);try{const c=(0,external_fs_.lstatSync)(o);return c.isSymbolicLink()?null:{name:l.name,isDir:c.isDirectory(),size:c.isFile()?c.size:void 0,mtime:c.mtimeMs}}catch{return null}})).filter(Boolean).sort(((l,o)=>o.isDir-l.isDir||l.name.localeCompare(o.name))),u=t?t.replace(/\\/g,"/"):"",f=u.includes("/")?u.slice(0,u.lastIndexOf("/")):u?"":null;i.json({ok:!0,cwd:n.cwd,path:u,parent:f,entries:s})}catch(s){i.status(500).json({error:s.message})}})),app.get("/api/files/:sessionId/search",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=String(d.query.q||"").trim().toLowerCase();try{let e=server_walkFiles(n.cwd,"",[],0,["node_modules"],!0).map((u=>({name:u.name,dir:!!u.dir,mtime:u.mtime})));t&&(e=e.filter((u=>u.name.toLowerCase().includes(t))));const s=u=>{if(!t)return 0;const f=u.name.slice(u.name.lastIndexOf("/")+1).toLowerCase();return f.startsWith(t)?0:f.includes(t)?1:2};e.sort(((u,f)=>s(u)-s(f)||(f.mtime||0)-(u.mtime||0))),i.json({ok:!0,files:e.slice(0,50).map((u=>({name:u.name,dir:!!u.dir})))})}catch(e){i.status(500).json({error:e.message})}})),app.get("/api/files/:sessionId/at-ls",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=process.platform==="win32",e=String(d.query.dir||"").replace(/\\/g,"/"),s=String(d.query.q||"").toLowerCase(),u=l=>l.replace(/\\/g,"/");if(t&&e==="/"){const l="CDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((o=>o+":")).filter((o=>{try{return(0,external_fs_.existsSync)(o+"\\")}catch{return!1}})).filter((o=>!s||o.toLowerCase().startsWith(s))).map((o=>({label:o,dir:!0})));return i.json({ok:!0,win:t,abs:"/",rel:!1,parent:null,entries:l})}let f;e?e==="~"||e.startsWith("~/")?f=(0,external_path_.join)((0,external_os_.homedir)(),e.slice(1)):t&&/^[A-Za-z]:/.test(e)?f=e.length===2?e+"/":e:e.startsWith("/")?f=e:f=(0,external_path_.join)(n.cwd,e):f=n.cwd,f=(0,external_path_.resolve)((0,external_path_.normalize)(f));try{const l=(0,external_fs_.readdirSync)(f,{withFileTypes:!0}).filter((a=>a.name!==".git")).map((a=>{try{const h=(0,external_fs_.lstatSync)((0,external_path_.join)(f,a.name));return h.isSymbolicLink()||!(h.isDirectory()||h.isFile())?null:{label:a.name,dir:h.isDirectory()}}catch{return null}})).filter(Boolean),o=a=>s?a.label.toLowerCase().startsWith(s)?0:1:0,c=l.filter((a=>!s||a.label.toLowerCase().includes(s))).filter((a=>s.startsWith(".")||!a.label.startsWith("."))).sort(((a,h)=>o(a)-o(h)||h.dir-a.dir||a.label.localeCompare(h.label,"zh"))).slice(0,300),r=(0,external_path_.dirname)(f);i.json({ok:!0,win:t,abs:u(f),rel:!e||!/^([/~]|[A-Za-z]:)/.test(e),parent:r!==f?u(r):t?"/":null,entries:c})}catch(l){i.status(l.code==="ENOENT"||l.code==="ENOTDIR"?404:500).json({error:l.code==="ENOENT"?"\u76EE\u5F55\u4E0D\u5B58\u5728":l.code==="ENOTDIR"?"\u4E0D\u662F\u76EE\u5F55":l.message})}}));const _viewTokens=new Map;app.post("/api/files/:sessionId/view-token",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({ok:!1,error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=Date.now();for(const[s,u]of _viewTokens)u.exp<t&&_viewTokens.delete(s);let e=[..._viewTokens].find((([,s])=>s.sid===n.id&&s.cwd===n.cwd&&s.exp-t>36e5))?.[0];e||(e=(0,external_crypto_.randomBytes)(18).toString("base64url"),_viewTokens.set(e,{sid:n.id,cwd:n.cwd,exp:t+2*36e5})),i.json({ok:!0,token:e,cwd:n.cwd})})),app.get("/view/:token/*",((d,i)=>{const n=_viewTokens.get(d.params.token);if(!n||n.exp<Date.now())return i.status(403).send("\u9884\u89C8\u94FE\u63A5\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u56DE\u5230 myhi \u91CD\u65B0\u6253\u5F00");const t=safePath(n.cwd,d.params[0]||"");if(!t)return i.status(403).send("\u8DEF\u5F84\u8D8A\u754C");i.setHeader("Content-Security-Policy","sandbox allow-scripts allow-popups allow-forms allow-modals allow-downloads"),i.setHeader("X-Content-Type-Options","nosniff"),i.setHeader("Cache-Control","no-cache"),i.sendFile(t,{dotfiles:"allow"},(e=>{e&&!i.headersSent&&i.status(404).send("\u6587\u4EF6\u4E0D\u5B58\u5728")}))}));const _zipTickets=new Map;app.post("/api/files/:sessionId/zip-ticket",checkAuth,express.json({limit:"1mb"}),((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({ok:!1,error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=Array.isArray(d.body?.paths)?d.body.paths.map(String).filter(Boolean).slice(0,2e3):[];if(!t.length)return i.status(400).json({ok:!1,error:"\u6CA1\u6709\u9009\u62E9\u8981\u4E0B\u8F7D\u7684\u6587\u4EF6"});const e=[];for(const a of t){const h=safePath(n.cwd,a);if(!h)return i.status(403).json({ok:!1,error:"\u8DEF\u5F84\u8D8A\u754C\uFF1A"+a});e.push({abs:h,name:a.replace(/\\/g,"/").replace(/\/+$/,"").split("/").pop()})}const{files:s,bytes:u,skipped:f}=collectZipFiles(e);if(!s.length)return i.status(400).json({ok:!1,error:"\u9009\u4E2D\u7684\u5185\u5BB9\u91CC\u6CA1\u6709\u6587\u4EF6\uFF08\u7A7A\u6587\u4EF6\u5939\uFF0C\u6216\u53EA\u6709\u88AB\u8DF3\u8FC7\u7684 .git / node_modules \u7B49\uFF09"});if(s.length>ZIP_MAX_FILES)return i.status(413).json({ok:!1,error:`\u6587\u4EF6\u592A\u591A\uFF08\u8D85\u8FC7 ${ZIP_MAX_FILES} \u4E2A\uFF09\uFF0C\u8BF7\u5206\u51E0\u6279\u4E0B\u8F7D`});if(u>ZIP_MAX_BYTES)return i.status(413).json({ok:!1,error:`\u603B\u5927\u5C0F ${(u/1024**3).toFixed(1)} GB \u8D85\u8FC7 4GB\uFF0C\u8BF7\u5206\u51E0\u6279\u4E0B\u8F7D\uFF08\u6216\u7528\u9996\u9875\u4EFB\u52A1 \u22EF \u2192\u300C\u8FC1\u79FB\u5230\u53E6\u4E00\u53F0 myhi\u300D\u6253\u5305\uFF09`});const l=Date.now();for(const[a,h]of _zipTickets)h.exp<l&&_zipTickets.delete(a);const c=(e.length===1?e[0].name:null)||`${String(n.title||"files").replace(/[\\/:*?"<>|]+/g,"_").slice(0,40)}-${e.length}\u9879`,r=(0,external_crypto_.randomBytes)(12).toString("hex");_zipTickets.set(r,{sid:n.id,files:s,name:c+".zip",exp:l+10*6e4}),i.json({ok:!0,ticket:r,name:c+".zip",files:s.length,bytes:u,skipped:f})})),app.get("/api/files/:sessionId/zip",checkAuth,(async(d,i)=>{const n=_zipTickets.get(String(d.query.ticket||""));if(!n||n.sid!==d.params.sessionId||n.exp<Date.now())return i.status(410).send("\u4E0B\u8F7D\u94FE\u63A5\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u56DE\u5230 myhi \u91CD\u65B0\u70B9\u4E0B\u8F7D");_zipTickets.delete(String(d.query.ticket)),i.setHeader("Content-Type","application/zip"),i.setHeader("Content-Disposition",`attachment; filename="download.zip"; filename*=UTF-8''${encodeURIComponent(n.name)}`);try{await writeZip(i,n.files),i.end()}catch(t){console.warn("[files] \u6253\u5305\u4E0B\u8F7D\u4E2D\u65AD:",t.message),i.destroy()}})),app.get("/api/files/:sessionId/download",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=d.query.path;if(!t)return i.status(400).json({error:"\u7F3A\u5C11 path \u53C2\u6570"});const e=safePath(n.cwd,t);if(!e)return i.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});let s;try{s=(0,external_fs_.statSync)(e)}catch{return i.status(404).json({error:"\u6587\u4EF6\u4E0D\u5B58\u5728"})}if(!s.isFile())return i.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});const u=t.split("/").pop(),f=d.query.inline==="1"&&/\.(png|jpe?g|gif|webp|bmp|ico|avif|svg|pdf|mp4|webm|ogv|mov|m4v|mp3|wav|ogg|oga|m4a|flac|aac|opus)$/i.test(u);i.setHeader("Content-Disposition",`${f?"inline":"attachment"}; filename*=UTF-8''${encodeURIComponent(u)}`),f&&/\.svg$/i.test(u)&&i.setHeader("Content-Security-Policy","sandbox; default-src 'none'; img-src data:; style-src 'unsafe-inline'"),i.sendFile(e,{dotfiles:"allow",acceptRanges:!0},(l=>{if(!l)return;const o=l.code||"";["ECONNABORTED","EPIPE","ECONNRESET"].includes(o)||i.writableEnded||(console.warn("[files] \u4E0B\u8F7D\u5931\u8D25:",t,o||l.message),i.headersSent?i.destroy():i.status(500).json({error:"\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25: "+(o||l.message)}))}))})),app.post("/api/files/:sessionId/upload",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=(d.query.path||"").replace(/\\/g,"/"),e=safePath(n.cwd,t);if(!e)return i.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});(0,external_fs_.mkdirSync)(e,{recursive:!0}),multer({storage:multer.diskStorage({destination:(s,u,f)=>{u.originalname=Buffer.from(u.originalname,"latin1").toString("utf8");const l=u.originalname.includes("/")?u.originalname.slice(0,u.originalname.lastIndexOf("/")):"",o=l?(0,external_path_.join)(e,l):e,c=(0,external_path_.resolve)((0,external_path_.normalize)(o)),r=(0,external_path_.resolve)((0,external_path_.normalize)(n.cwd));if(c!==r&&!c.startsWith(r+external_path_.sep))return f(new Error("\u8DEF\u5F84\u8D8A\u754C"));(0,external_fs_.mkdirSync)(o,{recursive:!0}),f(null,o)},filename:(s,u,f)=>{const l=u.originalname.includes("/")?u.originalname.slice(u.originalname.lastIndexOf("/")+1):u.originalname;f(null,l)}}),limits:{fileSize:500*1024*1024}}).array("files",100)(d,i,(s=>{if(s)return i.status(400).json({error:s.message});if(!d.files?.length)return i.status(400).json({error:"\u6CA1\u6709\u6587\u4EF6"});const u=d.files.map((f=>({name:f.originalname,size:f.size,path:(0,external_path_.resolve)(f.path).replace(/\\/g,"/")})));io.emit("files:changed",{sessionId:n.id}),i.json({ok:!0,files:u})}))})),app.delete("/api/files/:sessionId",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=d.query.path;if(!t)return i.status(400).json({error:"\u7F3A\u5C11 path \u53C2\u6570"});const e=safePath(n.cwd,t);if(!e)return i.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)(n.cwd)))return i.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:n.id}),i.json({ok:!0})}catch(s){i.status(500).json({error:s.message})}})),app.get("/api/files/:sessionId/manifest",checkAuth,(async(d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=d.query.path||"",e=safePath(n.cwd,t);if(!e)return i.status(403).json({error:"\u8DEF\u5F84\u8D8A\u754C"});try{const s=server_walkFiles(e,""),u=[];for(const f of s){if(f.size>=50*1024*1024){u.push(f);continue}try{const l=await fileHash((0,external_path_.join)(e,f.name));u.push({...f,hash:l})}catch{u.push(f)}}i.json({ok:!0,cwd:n.cwd,path:t,files:u})}catch(s){i.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(d){return String(d||"").replace(/\\/g,"/").replace(/^\/+/,"")}function editableTarget(d,i){const n=normRelPath(i);if(!n)return{error:"\u7F3A\u5C11 path",code:400};const t=safePath(d.cwd,n);if(!t)return{error:"\u8DEF\u5F84\u8D8A\u754C",code:403};const e=(n.split("/").pop().match(/\.([A-Za-z0-9]+)$/)||[])[1]?.toLowerCase()||"";return EDITABLE_EXTS.has(e)?{rel:n,target:t}:{error:"\u8BE5\u7C7B\u578B\u6587\u4EF6\u4E0D\u652F\u6301\u5728\u7EBF\u7F16\u8F91\uFF0C\u8BF7\u7528\u4E0B\u8F7D",code:415}}function looksBinary(d){const i=Math.min(d.length,8192);for(let n=0;n<i;n++)if(d[n]===0)return!0;return!1}function findBySuffix(d,i){const n=server_walkFiles(d,"",[],0,["node_modules"],!1,2e4).filter((e=>e.name.endsWith("/"+i)));if(!n.length)return null;const t=e=>e.name.split("/").length;return n.sort(((e,s)=>t(e)-t(s)||s.mtime-e.mtime)),n[0].name}app.get("/api/files/:sessionId/content",checkAuth,((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});let t=editableTarget(n,d.query.path);if(t.error)return i.status(t.code).json({error:t.error});if(!(0,external_fs_.existsSync)(t.target)&&!(0,external_path_.isAbsolute)(t.rel)){const u=findBySuffix(n.cwd,t.rel);u&&(t=editableTarget(n,u))}let e;try{e=(0,external_fs_.statSync)(t.target)}catch{return i.status(404).json({error:"\u6587\u4EF6\u4E0D\u5B58\u5728"})}if(!e.isFile())return i.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});if(e.size>EDIT_MAX_BYTES)return i.status(413).json({error:"\u6587\u4EF6\u8D85\u8FC7 2MB\uFF0C\u4EC5\u652F\u6301\u4E0B\u8F7D"});let s;try{s=(0,external_fs_.readFileSync)(t.target)}catch(u){return i.status(500).json({error:"\u8BFB\u53D6\u5931\u8D25: "+(u.code||u.message)})}if(looksBinary(s))return i.status(415).json({error:"\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u4EC5\u652F\u6301\u4E0B\u8F7D"});i.json({ok:!0,path:t.rel,name:t.rel.split("/").pop(),content:s.toString("utf8"),mtime:e.mtimeMs,size:e.size,md:/\.(md|markdown)$/i.test(t.rel)})})),app.put("/api/files/:sessionId/content",checkAuth,express.json({limit:"4mb"}),((d,i)=>{const n=manager.get(d.params.sessionId);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{content:t,baseMtime:e,force:s}=d.body||{};if(typeof t!="string")return i.status(400).json({error:"\u7F3A\u5C11\u5185\u5BB9"});if(Buffer.byteLength(t,"utf8")>EDIT_MAX_BYTES)return i.status(413).json({error:"\u5185\u5BB9\u8D85\u8FC7 2MB"});const u=editableTarget(n,d.body.path);if(u.error)return i.status(u.code).json({error:u.error});let f;try{f=(0,external_fs_.statSync)(u.target)}catch{return i.status(404).json({error:"\u6587\u4EF6\u5DF2\u88AB\u5220\u9664\uFF0C\u65E0\u6CD5\u4FDD\u5B58"})}if(!f.isFile())return i.status(400).json({error:"\u4E0D\u662F\u6587\u4EF6"});if(!s&&typeof e=="number"&&Math.abs(f.mtimeMs-e)>300)return i.status(409).json({error:"conflict",mtime:f.mtimeMs});const l=u.target+".myhi-edit-"+Date.now();try{try{(0,external_fs_.writeFileSync)(l,t,"utf8"),(0,external_fs_.renameSync)(l,u.target)}catch{try{(0,external_fs_.rmSync)(l,{force:!0})}catch{}(0,external_fs_.writeFileSync)(u.target,t,"utf8")}}catch(c){const r=["EBUSY","EPERM","EACCES"].includes(c.code);return console.warn("[files] \u4FDD\u5B58\u5931\u8D25:",u.rel,c.code||c.message),i.status(500).json({error:r?"\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: "+(c.code||c.message)})}let o=Date.now();try{o=(0,external_fs_.statSync)(u.target).mtimeMs}catch{}io.emit("files:changed",{sessionId:n.id}),i.json({ok:!0,mtime:o})})),app.get("/api/me",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie);i.json({name:n?.name||"\u7528\u6237",role:n?.role||"admin",exclusive:isExclusiveMode(),hasUsers:hasUsers(),multiUser:isMultiUser(),member:!!n?.member,dir:n?.dir||null,defaultRoot:n?.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:""}}}const maskKey=d=>d?d.length>12?d.slice(0,6)+"***"+d.slice(-4):"***":"";app.get("/api/gateway",adminBearerOr(checkAuth,requireAdmin),((d,i)=>{const n=loadGateway(),t=resolveGateway();i.json({baseUrl:n.baseUrl||"",apiKey:maskKey(n.apiKey),hasKey:!!n.apiKey,effective:t.baseUrl?{baseUrl:t.baseUrl,apiKey:maskKey(t.apiKey),source:t.source}:null})})),app.post("/api/gateway",adminBearerOr(checkAuth,requireAdmin),express.json(),((d,i)=>{const{baseUrl:n,apiKey:t}=d.body||{},e=loadGateway(),s={baseUrl:typeof n=="string"?n.trim():e.baseUrl,apiKey:!t||t.includes("***")?e.apiKey:t.trim()};try{(0,external_fs_.mkdirSync)(server_configDir,{recursive:!0}),(0,external_fs_.writeFileSync)(gatewayFile,JSON.stringify(s,null,2),{mode:384}),i.json({ok:!0})}catch(u){i.status(500).json({error:u.message})}})),app.get("/api/secrets",checkAdminAuth,((d,i)=>{try{i.json(secretsOverview())}catch(n){i.status(500).json({error:n.message})}})),app.post("/api/secrets",checkAdminAuth,express.json(),((d,i)=>{const{name:n,value:t,type:e,scope:s,cwd:u}=d.body||{},f=upsertSecret({name:n,value:t,type:e,scope:s,cwd:u});if(f.error)return i.status(400).json(f);i.json(f)})),app.delete("/api/secrets",checkAdminAuth,express.json(),((d,i)=>{const{name:n,scope:t,cwd:e}=d.body||{};if(!n)return i.status(400).json({error:"\u7F3A\u5C11 name"});try{i.json(deleteSecret({name:n,scope:t,cwd:e}))}catch(s){i.status(500).json({error:s.message})}})),app.get("/api/session/:id/secrets",checkAuth,((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});i.json({cwd:n.cwd,project:listSecrets("project",n.cwd),global:listSecrets("global")})})),app.post("/api/session/:id/secrets",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:t,value:e,type:s}=d.body||{},u=upsertSecret({name:t,value:e,type:s,scope:"project",cwd:n.cwd});if(u.error)return i.status(400).json(u);i.json(u)})),app.delete("/api/session/:id/secrets",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:t}=d.body||{};if(!t)return i.status(400).json({error:"\u7F3A\u5C11 name"});i.json(deleteSecret({name:t,scope:"project",cwd:n.cwd}))})),app.post("/api/session/:id/secrets/bulk",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=upsertManyProject(n.cwd,(d.body||{}).text||"");if(t.error)return i.status(400).json(t);i.json(t)})),app.get("/api/session/:id/guard",checkAuth,((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=getProjectGuard(n.cwd);i.json({cwd:n.cwd,enabled:t.enabled,level:t.level,entities:t.entities})})),app.put("/api/session/:id/guard",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{enabled:t,level:e}=d.body||{},s=setProjectGuard(n.cwd,{enabled:t,level:e});if(s.error)return i.status(400).json(s);i.json(s)})),app.post("/api/session/:id/guard/entity",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:t,type:e}=d.body||{},s=upsertEntity(n.cwd,{name:t,type:e});if(s.error)return i.status(400).json(s);i.json(s)})),app.delete("/api/session/:id/guard/entity",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const{name:t}=d.body||{};if(!t)return i.status(400).json({error:"\u7F3A\u5C11 name"});i.json(deleteEntity(n.cwd,t))})),app.post("/api/session/:id/guard/bulk",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=upsertManyEntities(n.cwd,(d.body||{}).text||"");if(t.error)return i.status(400).json(t);i.json(t)})),app.get("/api/session/:id/guard/audit",checkAuth,((d,i)=>{const n=manager.get(d.params.id);if(!n)return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728"});const t=n.claudeSessionId||d.params.id;i.json({entries:loadAudit(t)})})),app.get("/api/session/:id/followup",checkAuth,((d,i)=>{const n=manager.get(d.params.id);if(!n||typeof n.followUpState!="function")return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728\u6216\u975E AI \u4F1A\u8BDD"});i.json(n.followUpState())})),app.put("/api/session/:id/followup",checkAuth,express.json(),((d,i)=>{const n=manager.get(d.params.id);if(!n||typeof n.setFollowUp!="function")return i.status(404).json({error:"\u4F1A\u8BDD\u4E0D\u5B58\u5728\u6216\u975E AI \u4F1A\u8BDD"});const{enabled:t,intervalMinutes:e}=d.body||{};i.json(n.setFollowUp({enabled:t,intervalMinutes:e}))}));function maybeKickRelay(d){try{if(!d?.autoSend)return;const i=manager.get(d.sessionId);i&&typeof i._maybeRelayDraft=="function"&&i.alive&&!i.isBusy&&i._maybeRelayDraft()}catch{}}app.get("/api/inbox",checkAuth,((d,i)=>{const n=getUserInfo(d.headers.cookie),{sessionId:t}=d.query;try{try{rebindDrafts(manager.listSessions())}catch{}const e=new Set(manager.list(n?.name,n?.role==="admin").map((l=>l.id))),s=listDrafts({sessionId:t||void 0}).filter((l=>e.has(l.sessionId)||l.owner&&l.owner===n?.name)),u={};for(const l of s)u[l.sessionId]=(u[l.sessionId]||0)+1;const f=new Set(manager.listSessions().map((l=>l.id)));i.json({drafts:s.map((l=>({...l,sessionAlive:f.has(l.sessionId)}))),counts:u})}catch(e){i.status(500).json({error:e.message})}})),app.post("/api/inbox",checkAuth,express.json({limit:"1mb"}),((d,i)=>{const n=getUserInfo(d.headers.cookie),t=d.body||{},e=t.sessionId?manager.get(t.sessionId):null;try{const s=addDraft({...t,owner:t.owner||n?.name||null},e);maybeKickRelay(s),i.json({ok:!0,draft:s})}catch(s){i.status(400).json({error:s.message})}})),app.put("/api/inbox/:id",checkAuth,express.json({limit:"1mb"}),((d,i)=>{const n=d.body||{},t=n.sessionId?manager.get(n.sessionId):null,e=updateDraft(d.params.id,n,t);if(!e)return i.status(404).json({error:"\u8349\u7A3F\u4E0D\u5B58\u5728"});maybeKickRelay(e),i.json({ok:!0,draft:e})})),app.post("/api/inbox/reorder",checkAuth,express.json(),((d,i)=>{const{sessionId:n,ids:t}=d.body||{};if(!n||!Array.isArray(t))return i.status(400).json({error:"\u53C2\u6570\u4E0D\u5BF9"});reorderDrafts(n,t.map(String)),i.json({ok:!0})})),app.post("/api/inbox/merge",checkAuth,express.json(),((d,i)=>{try{const n=mergeDrafts((d.body?.ids||[]).map(String));maybeKickRelay(n),i.json({ok:!0,draft:n})}catch(n){i.status(400).json({error:n.message})}})),app.post("/api/inbox/:id/unmerge",checkAuth,((d,i)=>{try{i.json({ok:!0,drafts:unmergeDraft(d.params.id)})}catch(n){i.status(400).json({error:n.message})}})),app.post("/api/inbox/resume",checkAuth,express.json(),((d,i)=>{const n=manager.get(String(d.body?.sessionId||""));if(!n||typeof n._maybeRelayDraft!="function")return i.status(404).json({error:"\u4EFB\u52A1\u4E0D\u5B58\u5728"});if(n.isBusy)return i.json({ok:!0,busy:!0});n._maybeRelayDraft(),i.json({ok:!0})})),app.delete("/api/inbox/:id",checkAuth,((d,i)=>{if(!removeDraft(d.params.id))return i.status(404).json({error:"\u8349\u7A3F\u4E0D\u5B58\u5728"});i.json({ok:!0})}));function _spawnOpen(d,i,n=process.platform==="win32"){return new Promise((t=>{try{const e=(0,external_child_process_namespaceObject.spawn)(d,i,{detached:!0,stdio:"ignore",shell:n});e.on("error",(s=>{console.warn("[open-folder]",d,"\u5931\u8D25:",s.message),t(!1)})),e.unref(),setTimeout((()=>t(!0)),300)}catch(e){console.warn("[open-folder] spawn \u5F02\u5E38:",e.message),t(!1)}}))}let _winSessionId;process.platform==="win32"&&(0,external_child_process_namespaceObject.execFile)("tasklist",["/FI",`PID eq ${process.pid}`,"/FO","CSV","/NH"],{windowsHide:!0,timeout:5e3},((d,i)=>{const n=!d&&String(i).match(/^"[^"]*","\d+","[^"]*","(\d+)"/m);_winSessionId=n?Number(n[1]):null,_winSessionId===0&&console.log("[open-folder] myhi \u8FD0\u884C\u5728\u540E\u53F0\u4F1A\u8BDD\uFF08Session 0\uFF09\uFF0C\u300C\u6253\u5F00\u6587\u4EF6\u5939\u300D\u5DF2\u505C\u7528")}));function hasDesktop(){return process.platform==="linux"?!!(process.env.DISPLAY||process.env.WAYLAND_DISPLAY):process.platform==="win32"?_winSessionId!==0:!0}const NO_DESKTOP_MSG="myhi \u5F53\u524D\u4EE5\u540E\u53F0\u670D\u52A1\u65B9\u5F0F\u8FD0\u884C\uFF08\u6CA1\u6709\u684C\u9762\uFF09\uFF0C\u65E0\u6CD5\u5728\u672C\u673A\u5F39\u51FA\u6587\u4EF6\u5939\u7A97\u53E3\uFF0C\u8BF7\u7528\u300C\u6587\u4EF6\u300D\u9762\u677F\u6D4F\u89C8/\u4E0B\u8F7D";app.post("/api/session/:id/open-folder",checkAuth,(async(d,i)=>{const n=manager.get(d.params.id);if(!n?.cwd)return i.status(404).json({error:"\u4F1A\u8BDD\u6216\u76EE\u5F55\u4E0D\u5B58\u5728"});if(!(0,external_fs_.existsSync)(n.cwd))return i.status(400).json({error:"\u76EE\u5F55\u4E0D\u5B58\u5728\uFF08\u53EF\u80FD\u88AB\u79FB\u52A8/\u5220\u9664\uFF09: "+n.cwd});if(!hasDesktop())return i.json({ok:!1,cwd:n.cwd,error:NO_DESKTOP_MSG});let t=n.cwd;if(process.platform==="win32"){t=t.replace(/\//g,"\\").replace(/(?<!^[A-Za-z]:)\\+$/,"");let s=await _spawnOpen("explorer.exe",[t],!1);s||(s=await _spawnOpen("cmd.exe",["/c","start","",t]));const u=t.split("\\").filter(Boolean).pop()||"";if(u){const f=`$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",f],!1)}return console.log("[open-folder]",t,s?"\u5DF2\u62C9\u8D77":"\u5931\u8D25"),i.json({ok:s,cwd:t})}const e=process.platform==="darwin"?await _spawnOpen("open",[t]):await _spawnOpen("xdg-open",[t]);i.json({ok:e,cwd:t})}));function getPkgVersion(){for(const d of["../package.json","./package.json","package.json"])try{const i=JSON.parse((0,external_fs_.readFileSync)((0,external_path_.join)(server_dirname,d),"utf8")).version;if(i&&i!=="0.0.0")return i}catch{}return"0.0.0"}const PKG_VERSION=getPkgVersion();let _latestVersion=null,_lastVersionCheck=0;const VERSION_CHECK_INTERVAL=600*1e3;async function checkLatestVersion(){const d=Date.now();if(_latestVersion&&d-_lastVersionCheck<VERSION_CHECK_INTERVAL)return _latestVersion;const i=await latestVersion("@wendongfly/myhi",npmRegistryPref());return i&&(_latestVersion=i.version,_lastVersionCheck=d),_latestVersion}function npmRegistryPref(){return _configString("npmRegistry")||"auto"}function semverGt(d,i){const n=String(d||"").split(/[.-]/).map(Number),t=String(i||"").split(/[.-]/).map(Number);for(let e=0;e<3;e++){const s=n[e]||0,u=t[e]||0;if(s!==u)return s>u}return!1}app.get("/api/version",(async(d,i)=>{const n=PKG_VERSION,t=await checkLatestVersion();i.json({current:n,latest:t||n,updateAvailable:!!t&&semverGt(t,n),upgrade:upgradeState()})}));function isSystemd(){return process.platform==="linux"&&process.ppid===1&&!!(process.env.INVOCATION_ID||process.env.JOURNAL_STREAM)}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{try{const d=[PKG_ROOT,"bin","daemon.js"].join(external_path_.sep),i=(0,external_fs_.openSync)((0,external_path_.join)(server_configDir,"daemon.log"),"a");(0,external_child_process_namespaceObject.spawn)(process.execPath,[d,...process.argv.slice(2)],{detached:!0,stdio:["ignore",i,i],windowsHide:!0,env:{...process.env,MYHI_WAIT_PID:String(process.pid)}}).unref(),console.log("[myhi] \u5DF2\u8F6C\u4E3A\u540E\u53F0\u8FD0\u884C\uFF08daemon\uFF09\uFF0C\u67E5\u770B\u65E5\u5FD7\uFF1Amyhi log")}catch(d){console.error("[myhi] \u62C9\u8D77 daemon \u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u91CD\u65B0\u8FD0\u884C myhi\uFF1A",d.message)}gracefulShutdown(),setTimeout((()=>process.exit(0)),300)}}app.get("/api/server-config",adminBearerOr(checkAuth),((d,i)=>{const n=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""}})();i.json({asrUrl:n||""})}));function requireAdmin(d,i,n){const t=getUserInfo(d.headers.cookie);if(t&&t.role!=="admin")return i.status(403).json({ok:!1,error:"\u4EC5\u7BA1\u7406\u5458\u53EF\u6267\u884C\u6B64\u64CD\u4F5C"});n()}const prefsFile=(0,external_path_.join)(server_configDir,"prefs.json"),PREF_KEYS=new Set(["theme","font","chat"]);function prefsKey(d){const i=getUserInfo(d.headers.cookie);return i&&i.role!=="admin"?"u:"+i.name:"admin"}function loadAllPrefs(){try{return JSON.parse((0,external_fs_.readFileSync)(prefsFile,"utf8").replace(/^\uFEFF/,""))||{}}catch{return{}}}app.get("/api/prefs",checkAuth,((d,i)=>i.json({ok:!0,prefs:loadAllPrefs()[prefsKey(d)]||null}))),app.put("/api/prefs",checkAuth,express.json({limit:"16kb"}),((d,i)=>{const n=d.body||{},t={};for(const[u,f]of Object.entries(n))PREF_KEYS.has(u)&&(t[u]=f);if(JSON.stringify(t).length>8192)return i.status(413).json({ok:!1,error:"\u504F\u597D\u6570\u636E\u8FC7\u5927"});const e=loadAllPrefs(),s=prefsKey(d);e[s]={...e[s]||{},...t,updatedAt:Date.now()};try{(0,external_fs_.writeFileSync)(prefsFile,JSON.stringify(e,null,2))}catch(u){return i.status(500).json({ok:!1,error:u.message})}i.json({ok:!0,updatedAt:e[s].updatedAt})})),app.post("/api/server-config",adminBearerOr(checkAuth,requireAdmin),express.json(),((d,i)=>{const{asrUrl:n}=d.body||{},t=(0,external_path_.join)((0,external_os_.homedir)(),".myhi","asr.json");try{const e=(n||"").trim();(0,external_fs_.writeFileSync)(t,JSON.stringify({url:e},null,2),"utf8"),i.json({ok:!0})}catch(e){i.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",adminBearerOr(checkAuth),((d,i)=>{i.json({name:machineName(),hostname:shortHostname(),fromEnv:!!process.env.MYHI_NAME})})),app.post("/api/machine-name",adminBearerOr(checkAuth,requireAdmin),express.json(),((d,i)=>{const n=String(d.body?.name??"").trim().slice(0,32),t=(0,external_path_.join)(server_configDir,"config.json");try{const e=_readConfig();n?e.name=n:delete e.name,(0,external_fs_.writeFileSync)(t,JSON.stringify(e,null,2),"utf8"),i.json({ok:!0,name:machineName()})}catch(e){i.status(500).json({error:e.message})}})),app.get("/api/models",checkAuth,(async(d,i)=>{const n=await listGatewayModels({force:d.query.refresh==="1"});i.json({ok:!0,...n,scenes:readSceneModels(),sceneLabels:SCENES,gatewaySource:resolveGateway().source})})),app.post("/api/model-scenes",adminBearerOr(checkAuth,requireAdmin),express.json(),((d,i)=>{const n=d.body||{};try{const t=_readConfig(),e={};for(const s of Object.keys(SCENES)){const u=String(n[s]??"").trim();if(u.length>120||/\s/.test(u))return i.status(400).json({ok:!1,error:`\u300C${SCENES[s]}\u300D\u7684\u6A21\u578B\u540D\u4E0D\u5BF9\uFF1A${u}`});u&&(e[s]=u)}t.models=e,("ask"in e||n.ask==="")&&delete t.askModel,(0,external_fs_.writeFileSync)((0,external_path_.join)(server_configDir,"config.json"),JSON.stringify(t,null,2),"utf8"),console.log("[myhi] \u573A\u666F\u6A21\u578B\u5DF2\u66F4\u65B0:",JSON.stringify(e)),i.json({ok:!0,scenes:readSceneModels()})}catch(t){i.status(500).json({ok:!1,error:"\u5199\u914D\u7F6E\u5931\u8D25\uFF1A"+t.message})}})),app.get("/api/server-mode",checkAuth,((d,i)=>{i.json({ok:!0,httpOnly:!_tlsOpts,fromEnv:!!process.env.MYHI_NO_HTTPS,port:PORT,configDir:server_configDir})})),app.post("/api/server-mode",adminBearerOr(checkAuth,requireAdmin),express.json(),((d,i)=>{const n=!!d.body?.httpOnly;if(process.env.MYHI_NO_HTTPS&&!n)return i.status(400).json({ok:!1,error:"\u542F\u52A8\u53C2\u6570\u91CC\u8BBE\u4E86\u73AF\u5883\u53D8\u91CF MYHI_NO_HTTPS\uFF0C\u5F3A\u5236 HTTP\uFF1B\u8981\u5207\u56DE HTTPS \u9700\u5148\u53BB\u6389\u5B83"});try{const t=_readConfig();t.httpOnly=n,(0,external_fs_.writeFileSync)((0,external_path_.join)(server_configDir,"config.json"),JSON.stringify(t,null,2),"utf8")}catch(t){return i.status(500).json({ok:!1,error:"\u5199\u914D\u7F6E\u5931\u8D25\uFF1A"+t.message})}console.log(`[myhi] \u7F51\u9875\u5207\u6362\u8BBF\u95EE\u534F\u8BAE \u2192 ${n?"HTTP":"HTTPS"}\uFF0C\u91CD\u542F\u751F\u6548\uFF08\u914D\u7F6E ${(0,external_path_.join)(server_configDir,"config.json")}\uFF09`),i.json({ok:!0,httpOnly:n,port:PORT}),setTimeout((()=>restartService()),500)})),app.get("/api/npm-registry",checkAuth,((d,i)=>{i.json({ok:!0,pref:npmRegistryPref()})})),app.post("/api/npm-registry",adminBearerOr(checkAuth,requireAdmin),express.json(),((d,i)=>{const n=String(d.body?.pref||"auto");if(!["auto","official","mirror"].includes(n))return i.status(400).json({ok:!1,error:"\u53EA\u80FD\u9009 auto / official / mirror"});try{const t=_readConfig();n==="auto"?delete t.npmRegistry:t.npmRegistry=n,(0,external_fs_.writeFileSync)((0,external_path_.join)(server_configDir,"config.json"),JSON.stringify(t,null,2),"utf8")}catch(t){return i.status(500).json({ok:!1,error:"\u5199\u914D\u7F6E\u5931\u8D25\uFF1A"+t.message})}_latestVersion=null,_latestClaude=null,i.json({ok:!0,pref:n})})),app.post("/api/restart",checkAuth,((d,i)=>{i.json({ok:!0}),setTimeout((()=>restartService()),300)}));const PKG_ROOT=(0,external_path_.join)(server_dirname,".."),DAEMON_CAPS=(process.env.MYHI_DAEMON_CAPS||"").split(",");let _upgrade={running:!1};function readLastUpgrade(){try{return JSON.parse((0,external_fs_.readFileSync)(upgradeStatusFile(server_configDir),"utf8"))}catch{return null}}function upgradeState(){if(_upgrade.running)return{running:!0,startedAt:_upgrade.startedAt,target:_upgrade.target};const d=_upgrade.result||readLastUpgrade();return d&&Date.now()-(d.at||0)<1800*1e3?{running:!1,last:d}:{running:!1}}function busyAgentTitles(){try{return manager.listSessions().filter((d=>d.mode==="agent"&&d.isBusy)).map((d=>d.title||d.id))}catch{return[]}}function recordUpgrade(d){d.at=Date.now(),_upgrade={running:!1,result:d};try{(0,external_fs_.writeFileSync)(upgradeStatusFile(server_configDir),JSON.stringify(d,null,2))}catch{}console.log(d.ok?`[myhi] \u5347\u7EA7\u6210\u529F\uFF1A${d.from} \u2192 ${d.to}`:`[myhi] \u5347\u7EA7\u5931\u8D25\uFF1A${d.error}`)}async function handleUpgrade(d,i){if(_upgrade.running)return i.status(409).json({ok:!1,error:"\u5347\u7EA7\u5DF2\u5728\u8FDB\u884C\u4E2D\uFF0C\u8BF7\u7A0D\u5019"});const n=busyAgentTitles();if(n.length&&!d.body?.force)return i.status(409).json({ok:!1,busy:n,error:`\u6709 ${n.length} \u4E2A\u4EFB\u52A1\u6B63\u5728\u6267\u884C\uFF1A${n.join("\u3001")}\u3002\u5347\u7EA7\u4F1A\u91CD\u542F\u670D\u52A1\u3001\u6253\u65AD\u5B83\u4EEC\u8FD9\u4E00\u8F6E\u3002`});const t=PKG_VERSION,{candidates:e,note:s}=await upgradeCandidates("@wendongfly/myhi",t,npmRegistryPref());if(!e.length)return i.json({ok:!1,error:s});const u=e[0].version;if(process.platform==="win32"&&process.send&&DAEMON_CAPS.includes("upgrade-v2")){_upgrade={running:!0,startedAt:Date.now(),target:u},i.json({ok:!0,mode:"daemon",from:t,target:u,message:"\u6B63\u5728\u505C\u6B62\u670D\u52A1\u5E76\u5B89\u88C5\u65B0\u7248\u672C\uFF0C\u7EA6 1~3 \u5206\u949F\uFF0C\u671F\u95F4\u9875\u9762\u4F1A\u65AD\u5F00\u2026"}),setTimeout((()=>process.send({type:"upgrade",target:u,candidates:e})),300);return}_upgrade={running:!0,startedAt:Date.now(),target:u},i.json({ok:!0,mode:"server",from:t,target:u,message:"\u6B63\u5728\u4E0B\u8F7D\u5B89\u88C5\u65B0\u7248\u672C\u2026"});const f=[];let l=null;for(const o of e){try{if(console.log(`[myhi] \u5347\u7EA7\uFF1A\u4ECE${registryName(o.registry)}\u5B89\u88C5 ${o.version}`),await execAsync(npmUpgradeCmd(PKG_ROOT,o.registry),{encoding:"utf8",timeout:6e5,windowsHide:!0}),l=checkInstall(PKG_ROOT,o.version),l.ok)break;f.push(`${registryName(o.registry)}\uFF1A${l.error}`)}catch(c){const r=(c.stderr||c.stdout||c.message||"").split(`
|
|
440
440
|
`).filter((a=>a.trim())).slice(-4).join(`
|
|
441
441
|
`);f.push(`${registryName(o.registry)}\uFF1Anpm install \u5931\u8D25
|
|
442
442
|
${r}`)}l=null}if(!l?.ok)return recordUpgrade({ok:!1,from:t,to:u,error:f.join(`
|