@wendongfly/myhi 1.3.153 → 1.3.154
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 +55 -0
- package/dist/index.js +1 -1
- package/dist/index.min.js +3 -3
- package/package.json +1 -1
package/dist/index.min.js
CHANGED
|
@@ -373,14 +373,14 @@ Content-Length: `+C+`\r
|
|
|
373
373
|
`,{mode:384})}catch{}}function loadAudit(S,d=500){if(!S)return[];try{return(0,external_fs_.readFileSync)(auditPath(S),"utf8").trim().split(`
|
|
374
374
|
`).filter(Boolean).slice(-d).map((n=>{try{return JSON.parse(n)}catch{return null}})).filter(Boolean)}catch{return[]}}function buildPseudonymizer(S,d){const l=getProjectGuard(S),n=d&&d.byVal?d:newMap();if(!l.enabled)return{enabled:!1,level:l.level,map:n,size:Object.keys(n.byVal).length,pseudonymize:i=>({text:i,count:0}),restore:i=>i};const e=LEVELS[l.level]||LEVELS[DEFAULT_LEVEL],o={};for(const[i,a]of Object.entries(n.byVal))o[a.ph]=i;function u(i,a){if(n.byVal[i])return n.byVal[i].ph;n.counters[a]=(n.counters[a]||0)+1;const t=`\u3010${a}_${n.counters[a]}\u3011`;return n.byVal[i]={ph:t,type:a},o[t]=i,t}function h(i){if(typeof i!="string"||!i||i.length>2e5)return{text:i,count:0};const a=[];e.pii&&a.push(...PII);const t=e.dict?l.entities:[];e.amount&&a.push(...AMOUNT);for(const v of a){const m=i.match(v.re);if(m)for(const b of m)n.byVal[b]||u(b,v.type)}for(const v of t)v.name&&i.includes(v.name)&&!n.byVal[v.name]&&u(v.name,v.type||"\u4E3B\u4F53");const r=Object.keys(n.byVal).filter((v=>i.includes(v)));r.sort(((v,m)=>m.length-v.length));let p=i,f=0;const s={};for(const v of r)if(p.includes(v)){const m=n.byVal[v].type;p=p.split(v).join(n.byVal[v].ph),f++,s[m]=(s[m]||0)+1}return{text:p,count:f,byType:s}}function c(i){return typeof i!="string"||!i||i.indexOf("\u3010")<0?i:i.replace(PLACEHOLDER_RE,(a=>o[a]!==void 0?o[a]:a))}return{enabled:!0,level:l.level,map:n,size:Object.keys(n.byVal).length,pseudonymize:h,restore:c}}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 S=JSON.parse((0,external_fs_.readFileSync)(INBOX_FILE,"utf8"));return Array.isArray(S)?S:[]}catch{return[]}}function saveDrafts(S){try{(0,external_fs_.mkdirSync)(CONFIG_DIR,{recursive:!0});const d=INBOX_FILE+".tmp";return(0,external_fs_.writeFileSync)(d,JSON.stringify(S,null,2),{mode:384}),(0,external_fs_.renameSync)(d,INBOX_FILE),!0}catch(d){return console.error("[inbox] \u5199\u5165\u5931\u8D25:",d.message),!1}}function projectNameOf(S){if(!S)return"";const d=String(S).replace(/\\/g,"/").split("/").filter(Boolean);return d[d.length-1]||""}function normAttach(S){return Array.isArray(S)?S.filter((d=>d&&typeof d.path=="string"&&d.path)).slice(0,10).map((d=>({path:d.path,name:d.name||d.path.split("/").pop()}))):[]}function listDrafts({sessionId:S,owner:d,includeAll:l=!0}={}){let n=loadDrafts();return S&&(n=n.filter((e=>e.sessionId===S))),d&&!l&&(n=n.filter((e=>!e.owner||e.owner===d))),n.sort(((e,o)=>(o.createdAt||0)-(e.createdAt||0)))}function countBySession(){const S={};for(const d of loadDrafts())d.sessionId&&(S[d.sessionId]=(S[d.sessionId]||0)+1);return S}function addDraft(S={},d=null){const l=String(S.text||"").slice(0,MAX_TEXT),n=normAttach(S.images),e=normAttach(S.files);if(!l.trim()&&!n.length&&!e.length)throw new Error("\u8349\u7A3F\u5185\u5BB9\u4E3A\u7A7A");if(!S.sessionId)throw new Error("\u8349\u7A3F\u5FC5\u987B\u5F52\u5C5E\u4E00\u4E2A\u4F1A\u8BDD");const o=d?.cwd||S.cwd||"",u={id:(0,external_crypto_.randomUUID)(),text:l,images:n,files:e,sessionId:S.sessionId,claudeSessionId:d?.claudeSessionId||S.claudeSessionId||null,sessionTitle:d?.title||S.sessionTitle||"(\u672A\u77E5\u4EFB\u52A1)",cwd:o,projectName:projectNameOf(o),owner:S.owner||d?.owner||null,autoSend:!!S.autoSend,source:S.source||"manual",createdAt:Date.now(),updatedAt:Date.now()},h=loadDrafts();for(h.push(u);h.length>MAX_DRAFTS;)h.shift();return saveDrafts(h),u}function updateDraft(S,d={},l=null){const n=loadDrafts(),e=n.findIndex((u=>u.id===S));if(e<0)return null;const o=n[e];return typeof d.text=="string"&&(o.text=d.text.slice(0,MAX_TEXT)),typeof d.autoSend=="boolean"&&(o.autoSend=d.autoSend),d.images&&(o.images=normAttach(d.images)),d.files&&(o.files=normAttach(d.files)),d.sessionId&&d.sessionId!==o.sessionId&&(o.sessionId=d.sessionId,o.claudeSessionId=l?.claudeSessionId||null,o.sessionTitle=l?.title||d.sessionTitle||o.sessionTitle,o.cwd=l?.cwd||d.cwd||o.cwd,o.projectName=projectNameOf(o.cwd)),o.updatedAt=Date.now(),n[e]=o,saveDrafts(n),o}function removeDraft(S){const d=loadDrafts(),l=d.filter((n=>n.id!==S));return l.length===d.length?!1:(saveDrafts(l),!0)}function rebindDrafts(S=[]){const d=new Map;for(const o of S)o.claudeSessionId&&d.set(o.claudeSessionId,o);const l=new Set(S.map((o=>o.id))),n=loadDrafts();let e=0;for(const o of n){if(l.has(o.sessionId)||!o.claudeSessionId)continue;const u=d.get(o.claudeSessionId);!u||u.id===o.sessionId||(o.sessionId=u.id,o.sessionTitle=u.title||o.sessionTitle,o.cwd=u.cwd||o.cwd,o.projectName=projectNameOf(o.cwd),e++)}return e&&saveDrafts(n),e}function syncSessionTitle(S,d){const l=loadDrafts();let n=!1;for(const e of l)e.sessionId===S&&e.sessionTitle!==d&&(e.sessionTitle=d,n=!0);n&&saveDrafts(l)}function buildDraftPrompt(S){const d=(S.text||"").trim(),l=S.images?.[0],n=S.files?.[0];return l?`\u7528\u6237\u4E0A\u4F20\u4E86\u4E00\u5F20\u56FE\u7247\uFF0C\u8DEF\u5F84\u662F ${l.path}\uFF0C\u8BF7\u7528 Read \u5DE5\u5177\u8BFB\u53D6\u8FD9\u5F20\u56FE\u7247\u3002\u7528\u6237\u7684\u8981\u6C42\u662F\uFF1A${d||"\u63CF\u8FF0\u56FE\u7247\u5185\u5BB9"}`:n?`\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 ${n.path}\uFF08\u539F\u6587\u4EF6\u540D ${n.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${d||"\u5206\u6790\u8FD9\u4E2A\u6587\u4EF6"}`:d}function nextAutoSendDraft(S){return S&&loadDrafts().filter((l=>l.sessionId===S&&l.autoSend)).sort(((l,n)=>(l.createdAt||0)-(n.createdAt||0)))[0]||null}function draftDisplayText(S){const d=(S.text||"").trim(),l=S.images?.[0],n=S.files?.[0];return l?`\u{1F4F7} ${d||"\u5206\u6790\u56FE\u7247"}`:n?`\u{1F4CE} ${n.name}${d?" "+d:""}`:d}let _launcher=null;function resolveWinLauncherFromCmd(S){try{const d=(0,external_fs_.readFileSync)(S,"utf8"),l=(0,external_path_.dirname)(S),n=o=>o.trim().replace(/%~?dp0%?/gi,l+"\\").replace(/\\{2,}/g,"\\");let e=d.match(/"?([^"\r\n]*claude\.exe)"?/i);if(e){const o=n(e[1]);if((0,external_fs_.existsSync)(o))return{command:o,preArgs:[]}}if(e=d.match(/"?([^"\r\n]*\.js)"?\s+%\*/i),e){const o=n(e[1]);if((0,external_fs_.existsSync)(o))return{command:process.execPath,preArgs:[o]}}}catch{}return null}function winLauncherFromPath(S){if(/\.exe$/i.test(S))return{command:S,preArgs:[]};if(/\.cmd$/i.test(S)){const d=resolveWinLauncherFromCmd(S);return d||{command:process.env.ComSpec||"cmd.exe",preArgs:["/c",S]}}return{command:S,preArgs:[]}}function findClaude(){if(_launcher)return _launcher;const S=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")],d=n=>process.platform==="win32"?winLauncherFromPath(n):{command:n,preArgs:[]},l=n=>console.log(`[agent] ${n} claude:`,_launcher.command,..._launcher.preArgs.length?[_launcher.preArgs[_launcher.preArgs.length-1]]:[]);for(const n of S)if((0,external_fs_.existsSync)(n))return _launcher=d(n),l("\u627E\u5230"),_launcher;try{const n=process.platform==="win32"?"where claude.cmd":"which claude",e=(0,external_child_process_namespaceObject.execSync)(n,{timeout:5e3,stdio:"pipe"}).toString().trim().split(`
|
|
375
375
|
`)[0].trim();if(e)return _launcher=d(e),l("which \u627E\u5230"),_launcher}catch{}return console.warn("[agent] \u672A\u627E\u5230 claude \u53EF\u6267\u884C\u6587\u4EF6\uFF0C\u56DE\u9000\u5230 PATH \u67E5\u627E"),_launcher=process.platform==="win32"?{command:process.env.ComSpec||"cmd.exe",preArgs:["/c","claude"]}:{command:"claude",preArgs:[]},_launcher}function resetClaudeLauncher(){_launcher=null}function getClaudeVersion(){return new Promise((S=>{let d;try{d=findClaude()}catch{return S(null)}let l="",n=!1;const e=h=>{n||(n=!0,S(h))};let o;try{o=(0,external_child_process_namespaceObject.spawn)(d.command,[...d.preArgs,"--version"],{stdio:["ignore","pipe","pipe"]})}catch{return e(null)}const u=setTimeout((()=>{try{o.kill()}catch{}e(null)}),1e4);o.stdout.on("data",(h=>{l+=h.toString()})),o.on("error",(()=>{clearTimeout(u),e(null)})),o.on("close",(()=>{clearTimeout(u);const h=l.match(/(\d+\.\d+\.\d+)/);e(h?{version:h[1],raw:l.trim()}:null)}))}))}const BASE64_STRIP_THRESHOLD=5*1024;function stripHeavyPayload(S){if(S==null||typeof S!="object")return S;if(Array.isArray(S))return S.map(stripHeavyPayload);const d={};for(const[l,n]of Object.entries(S))typeof n=="string"&&n.length>BASE64_STRIP_THRESHOLD&&(l==="data"||l==="url"&&n.startsWith("data:"))?d[l]=`[STRIPPED_BASE64_${n.length}_CHARS]`:d[l]=stripHeavyPayload(n);return d}const LOOP_POISON_PHRASES=["could not be processed and was removed","image exceeds","image dimensions exceed"],LOOP_MAX_POISON_HITS=2,POISON_MAX_NOTICE_LEN=4e3,LOOP_MAX_IDENTICAL_CALLS=3,LOOP_MAX_TURN_TOOLCALLS=120,LOOP_MAX_AUTO_RECOVER=2,IMAGE_NUDGE_STEP=15,STALL_WATCHDOG_MS=Number(process.env.MYHI_STALL_WATCHDOG_MS)||240*1e3,STALL_CHECK_INTERVAL_MS=30*1e3,RELAY_DELAY_MS=Number(process.env.MYHI_RELAY_DELAY_MS)||3e3,FOLLOW_UP_DEFAULT_MS=900*1e3,FOLLOW_UP_MAX=5,FOLLOW_UP_PROMPT="\u3010\u81EA\u52A8\u8DDF\u8FDB\xB7\u7CFB\u7EDF\u89E6\u53D1\u3011\u8BF7\u68C0\u67E5\u5F53\u524D\u6B63\u5728\u8FDB\u884C\u7684\u540E\u53F0\u4EFB\u52A1\u6216\u4E0A\u4E00\u6B65\u64CD\u4F5C\u7684\u8FDB\u5EA6\uFF1A\u6709\u65B0\u8FDB\u5C55\u5C31\u7B80\u8981\u6C47\u62A5\uFF1B\u4ECD\u5728\u8FDB\u884C\u5C31\u8BF4\u660E\u8FD8\u5728\u8DD1\u3001\u9884\u8BA1\u8FD8\u9700\u591A\u4E45\uFF1B\u82E5\u5DF2\u3010\u5168\u90E8\u5B8C\u6210\u3011\uFF0C\u8BF7\u6C47\u603B\u6700\u7EC8\u7ED3\u679C\uFF0C\u5E76\u5728\u56DE\u590D\u6700\u540E\u5355\u72EC\u4E00\u884C\u53EA\u5199 [\u8DDF\u8FDB\u5B8C\u6210]\uFF08\u7CFB\u7EDF\u636E\u6B64\u505C\u6B62\u81EA\u52A8\u8DDF\u8FDB\uFF09\u3002\u4E0D\u8981\u91CD\u590D\u5DF2\u6C47\u62A5\u8FC7\u7684\u5185\u5BB9\u3002",MYHI_SYSTEM_PROMPT=["\u56FE\u7247\u4E0E\u622A\u56FE\u5904\u7406\u7EA6\u675F\uFF08\u91CD\u8981\uFF0C\u7528\u4E8E\u907F\u514D API \u56FE\u7247\u9519\u8BEF\u4E0E\u6B7B\u5FAA\u73AF\uFF09\uFF1A","1. \u622A\u56FE\u4F18\u5148\u53EA\u622A\u5F53\u524D\u89C6\u53E3\uFF0C\u4E0D\u8981\u6574\u9875\u957F\u622A\u56FE\uFF1B\u56FE\u7247\u957F\u8FB9\u5C3D\u91CF \u22641568px\u3001\u9AD8\u5EA6\u4E0D\u8981\u8D85\u8FC7 8000px\uFF0C\u5426\u5219\u4F1A\u88AB API \u62D2\u7EDD\u3002",'2. \u82E5\u51FA\u73B0 "an image ... could not be processed and was removed" \u6216\u56FE\u7247\u88AB\u79FB\u9664\u7684\u9519\u8BEF\uFF0C\u8BF4\u660E\u8BE5\u56FE\u7247\u5DF2\u4E0D\u53EF\u7528\uFF0C'," \u4E0D\u8981\u7528 Read \u53CD\u590D\u91CD\u65B0\u8BFB\u53D6\u5B83\uFF1B\u8BF7\u57FA\u4E8E\u5DF2\u6709\u6587\u5B57\u4FE1\u606F\u7EE7\u7EED\uFF0C\u5FC5\u8981\u65F6\u8BF7\u7528\u6237\u91CD\u65B0\u4E0A\u4F20\u4E00\u5F20\u66F4\u5C0F\u7684\u622A\u56FE\u3002","3. \u540C\u4E00\u4E2A\u5DE5\u5177\u7528\u5B8C\u5168\u76F8\u540C\u7684\u53C2\u6570\u8FDE\u7EED\u5931\u8D25\u65F6\uFF0C\u4E0D\u8981\u539F\u6837\u91CD\u8BD5\uFF0C\u6362\u65B9\u6CD5\u6216\u8DF3\u8FC7\u3002","",'\u6267\u884C\u6A21\u5F0F\u7EA6\u675F\uFF08\u91CD\u8981\uFF09\uFF1A\u672C\u4F1A\u8BDD\u662F\u65E0\u4EBA\u503C\u5B88\u81EA\u52A8\u6267\u884C\u6A21\u5F0F\uFF0C\u6CA1\u6709"\u8BA1\u5212\u6A21\u5F0F"/"\u9000\u51FA\u8BA1\u5212"/\u5BA1\u6279\u5F39\u7A97/\u786E\u8BA4\u6309\u94AE/\u6587\u4EF6\u7F16\u8F91\u6388\u6743\u8FD9\u7C7B\u4EA4\u4E92\u3002','\u4F60\u60F3\u597D\u65B9\u6848\u5C31\u76F4\u63A5\u7528\u5DE5\u5177\u6267\u884C\uFF0C\u7EDD\u4E0D\u8981\u8BF4"\u7B49\u5F85\u6279\u51C6""\u8BF7\u70B9\u51FB\u786E\u8BA4\u6309\u94AE""\u6B63\u5728\u7B49\u5F85\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F""\u9700\u8981\u4F60\u6388\u6743"\u4E4B\u7C7B\u7684\u8BDD\u2014\u2014',"\u90A3\u4E9B UI \u5728\u8FD9\u91CC\u4E0D\u5B58\u5728\uFF0C\u8BF4\u4E86\u53EA\u4F1A\u8BA9\u4EFB\u52A1\u6C38\u4E45\u5361\u4F4F\u3002\u82E5\u67D0\u4E2A\u5DE5\u5177\u62A5\u6743\u9650/\u6388\u6743\u9519\u8BEF\uFF0C\u76F4\u63A5\u57FA\u4E8E\u73B0\u72B6\u7EE7\u7EED\u6216\u6362\u505A\u6CD5\uFF0C\u4E0D\u8981\u7A7A\u7B49\u7528\u6237\u70B9\u6309\u94AE\u3002","","\u6740\u8FDB\u7A0B\u7EA6\u675F\uFF08\u91CD\u8981\uFF0C\u4E8B\u5173\u672C\u4F1A\u8BDD\u5B58\u6D3B\uFF09\uFF1A\u6258\u7BA1\u4F60\u7684 myhi \u81EA\u5DF1\u5C31\u662F\u4E00\u4E2A node \u8FDB\u7A0B\uFF0C\u4F60\u662F\u5B83\u7684\u5B50\u8FDB\u7A0B\u3002","\u7EDD\u5BF9\u7981\u6B62\u6309\u300C\u8FDB\u7A0B\u540D\u300D\u6279\u91CF\u6740\u8FDB\u7A0B\uFF1Ataskkill /F /IM node.exe\u3001pkill node\u3001killall node\u3001Stop-Process -Name node \u5168\u90FD\u7981\u6B62\u2014\u2014","\u5B83\u4EEC\u4F1A\u628A myhi \u8FDE\u540C\u672C\u4F1A\u8BDD\u4E00\u8D77\u6740\u6B7B\uFF0C\u5DE5\u5177\u7ED3\u679C\u518D\u4E5F\u5199\u4E0D\u56DE\u6765\uFF0C\u8FD9\u6761\u547D\u4EE4\u4F1A\u6C38\u8FDC\u505C\u5728\u672A\u5B8C\u6210\u72B6\u6001\uFF0C","\u4E0B\u6B21 --resume \u53C8\u88AB\u91CD\u653E\u3001\u518D\u6740\u4E00\u6B21\uFF0C\u5F62\u6210\u65E0\u9650\u81EA\u6740\u5FAA\u73AF\uFF08\u771F\u5B9E\u53D1\u751F\u8FC7\uFF09\u3002","\u8981\u91CD\u542F\u67D0\u4E2A\u670D\u52A1\uFF0C\u5FC5\u987B\u7CBE\u786E\u5B9A\u4F4D\u90A3\u4E00\u4E2A\u8FDB\u7A0B\uFF1A\u5148\u6309\u5B83\u76D1\u542C\u7684\u7AEF\u53E3\u67E5 PID\uFF0C\u518D\u6309 PID \u6740\u3002","Windows: netstat -ano | findstr :<\u7AEF\u53E3> \u7136\u540E taskkill /F /PID <pid>\uFF1BLinux: lsof -ti:<\u7AEF\u53E3> | xargs -r kill\u3002","\u540C\u7406\uFF0C\u4E0D\u8981\u987A\u624B rm -rf \u6570\u636E\u76EE\u5F55/\u4E0A\u4F20\u76EE\u5F55\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u5220\u3002","","\u5B50\u4EE3\u7406\uFF08Task \u5DE5\u5177\uFF09\u4F7F\u7528\u5EFA\u8BAE\uFF1A\u9047\u5230\u300C\u5927\u8303\u56F4\u4EE3\u7801\u68C0\u7D22 / \u591A\u6587\u4EF6\u5BA1\u8BA1 / \u53EF\u5E76\u884C\u7684\u72EC\u7ACB\u5B50\u4EFB\u52A1 / \u9700\u8981\u6D77\u91CF\u8BFB\u53D6\u4F46\u53EA\u56DE\u7ED3\u8BBA\u300D\u8FD9\u7C7B\u91CD\u6D3B\uFF0C","\u4F18\u5148\u7528 Task \u5DE5\u5177\u8D77\u5B50\u4EE3\u7406\u53BB fan-out\u2014\u2014\u628A\u4E2D\u95F4\u8FC7\u7A0B\u9694\u79BB\u5728\u5B50\u4E0A\u4E0B\u6587\u91CC\u3001\u53EA\u628A\u7ED3\u8BBA\u6536\u56DE\u4E3B\u7EBF\uFF0C\u65E2\u7701\u4E3B\u4E0A\u4E0B\u6587\u53C8\u66F4\u5FEB\u3002","\u5B50\u4EE3\u7406\u5185\u90E8\u7684\u5DE5\u5177\u8C03\u7528\u4E0D\u4F1A\u6491\u7206\u4E3B\u7EBF\u7684\u5355\u8F6E\u5DE5\u5177\u9884\u7B97\uFF08\u5DF2\u8C41\u514D\uFF09\uFF0C\u653E\u5FC3\u7528\uFF1B\u4F46\u7B80\u5355\u7684\u5355\u6587\u4EF6\u5C0F\u6539\u52A8\u76F4\u63A5\u81EA\u5DF1\u505A\uFF0C\u4E0D\u5FC5\u8D77\u5B50\u4EE3\u7406\u3002"].join(`
|
|
376
|
-
`),VALID_PERMISSION_MODES=new Set(["bypassPermissions","plan","acceptEdits"]);function normalizePermissionMode(S){return S==="bypass"?"bypassPermissions":VALID_PERMISSION_MODES.has(S)?S:"bypassPermissions"}class AgentSession extends external_events_.EventEmitter{constructor(d,l={}){super(),this.id=d,this.createdAt=l.createdAt||new Date().toISOString(),this.title=l.title||"claude",this.cwd=l.cwd||process.env.MYHI_CWD||process.cwd(),this.tags=Array.isArray(l.tags)?l.tags:[],this.firstUserText=l.firstUserText||"",this.permissionMode=normalizePermissionMode(l.permissionMode),this.owner=l.owner||null,this.userDir=l.userDir||null,this.claudeSessionId=l.resumeSessionId||null,this.mode="agent",this.alive=!0,this._viewers=new Set,this._viewerNames=new Map,this.controlHolder=null,this.controlHolderName=null,this.lastInputTime=null,this._proc=null,this._busy=!1,this._interrupted=!1,this._buffer="",this._pendingResolve=null,this._pendingReject=null,this._keepAliveTimer=null,this._history=[],this._loopSigCounts=new Map,this._loopPoisonHits=0,this._loopTurnToolCalls=0,this._loopTripped=!1,this._loopAutoRecover=0,this._pendingSteer=null,this._followEnabled=!1,this._followIntervalMs=FOLLOW_UP_DEFAULT_MS,this._followMax=FOLLOW_UP_MAX,this._followCount=0,this._followTimer=null,this._relayTimer=null,this._followStopSignal=!1,this._imageBlockCount=0,this._imageNudgeAt=IMAGE_NUDGE_STEP,this._redactor=null,this._pseudo=null,this._pseudoMap=null,this._lastActivityAt=l.lastActivityAt||0,this._awaitingTool=!1,this._watchdogTimer=null,this._usage={totalCostUSD:0,totalInputTokens:0,totalOutputTokens:0,totalCacheReadTokens:0,totalCacheCreationTokens:0,queryCount:0,rateLimitInfo:null,modelUsage:{}},this.claudeSessionId&&this._loadResumedHistory()}_buildEnv(){const d={...process.env};if(delete d.CLAUDECODE,delete d.CLAUDE_CODE_ENTRYPOINT,delete d.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC,this.userDir){const l=(0,external_path_.join)(this.userDir,".gitconfig");(0,external_fs_.existsSync)(l)&&(d.GIT_CONFIG_GLOBAL=l)}try{const l=(0,external_path_.join)((0,external_os_.homedir)(),".myhi","gateway.json");if((0,external_fs_.existsSync)(l)){const n=JSON.parse((0,external_fs_.readFileSync)(l,"utf8"));n.baseUrl&&(d.ANTHROPIC_BASE_URL=n.baseUrl),n.apiKey&&(d.ANTHROPIC_API_KEY=n.apiKey)}}catch{}try{applySecretsToEnv(d,this.cwd)}catch{}return d}_buildArgs(){const d=["--output-format","stream-json","--input-format","stream-json","--verbose"];d.push("--append-system-prompt",MYHI_SYSTEM_PROMPT.replace(/\s*\n\s*/g," ").trim());const l=normalizePermissionMode(this.permissionMode);if(l==="bypassPermissions")d.push("--dangerously-skip-permissions");else if(l==="plan")d.push("--permission-mode","plan"),d.push("--allowedTools","WebSearch"),d.push("--allowedTools","WebFetch");else if(l==="acceptEdits"){d.push("--permission-mode","acceptEdits");const n=["Bash(git *)","Bash(npm *)","Bash(npx *)","Bash(node *)","Bash(ls *)","Bash(cat *)","Bash(mkdir *)","Bash(cp *)","Bash(mv *)","Bash(rm *)","Bash(cd *)","Bash(pwd)","Bash(find *)","Bash(grep *)","Bash(curl *)","Bash(wget *)","Bash(pip *)","Bash(python *)","Bash(python3 *)","Bash(chmod *)","Bash(chown *)","Bash(tar *)","Bash(unzip *)","Bash(zip *)","Bash(sed *)","Bash(awk *)","Bash(head *)","Bash(tail *)","Bash(wc *)","Bash(sort *)","Bash(echo *)","Bash(which *)","Bash(apt *)","Bash(apt-get *)","Bash(docker *)","Bash(ssh *)","Bash(scp *)","Bash(rsync *)","Bash(touch *)","Bash(diff *)","Bash(env *)","Bash(export *)","Bash(source *)","Bash(tee *)","Bash(xargs *)","Bash(du *)","Bash(df *)","Bash(ps *)","Bash(kill *)","Bash(systemctl *)","Bash(journalctl *)","Bash(sudo *)","Task","WebSearch","WebFetch"];for(const e of n)d.push("--allowedTools",e)}return this.modelId&&d.push("--model",this.modelId),this.claudeSessionId&&d.push("--resume",this.claudeSessionId),d}_writeStdin(d){if(!this._proc||!this._proc.stdin?.writable)return!1;try{return this._proc.stdin.write(JSON.stringify(d)+`
|
|
376
|
+
`),VALID_PERMISSION_MODES=new Set(["bypassPermissions","plan","acceptEdits"]);function normalizePermissionMode(S){return S==="bypass"?"bypassPermissions":VALID_PERMISSION_MODES.has(S)?S:"bypassPermissions"}class AgentSession extends external_events_.EventEmitter{constructor(d,l={}){super(),this.id=d,this.createdAt=l.createdAt||new Date().toISOString(),this.title=l.title||"claude",this.cwd=l.cwd||process.env.MYHI_CWD||process.cwd(),this.tags=Array.isArray(l.tags)?l.tags:[],this.firstUserText=l.firstUserText||"",this.permissionMode=normalizePermissionMode(l.permissionMode),this.owner=l.owner||null,this.userDir=l.userDir||null,this.claudeSessionId=l.resumeSessionId||null,this.mode="agent",this.alive=!0,this._viewers=new Set,this._viewerNames=new Map,this.controlHolder=null,this.controlHolderName=null,this.lastInputTime=null,this._proc=null,this._busy=!1,this._interrupted=!1,this._buffer="",this._pendingResolve=null,this._pendingReject=null,this._keepAliveTimer=null,this._history=[],this._loopSigCounts=new Map,this._loopPoisonHits=0,this._loopTurnToolCalls=0,this._loopTripped=!1,this._loopAutoRecover=0,this._pendingSteer=null,this._followEnabled=!1,this._followIntervalMs=FOLLOW_UP_DEFAULT_MS,this._followMax=FOLLOW_UP_MAX,this._followCount=0,this._followTimer=null,this._relayTimer=null,this._followStopSignal=!1,this._imageBlockCount=0,this._imageNudgeAt=IMAGE_NUDGE_STEP,this._redactor=null,this._pseudo=null,this._pseudoMap=null,this._lastActivityAt=l.lastActivityAt||0,this._awaitingTool=!1,this._watchdogTimer=null,this._usage={totalCostUSD:0,totalInputTokens:0,totalOutputTokens:0,totalCacheReadTokens:0,totalCacheCreationTokens:0,queryCount:0,rateLimitInfo:null,modelUsage:{}},this._contextTokens=0,this.claudeSessionId&&this._loadResumedHistory()}_buildEnv(){const d={...process.env};if(delete d.CLAUDECODE,delete d.CLAUDE_CODE_ENTRYPOINT,delete d.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC,this.userDir){const l=(0,external_path_.join)(this.userDir,".gitconfig");(0,external_fs_.existsSync)(l)&&(d.GIT_CONFIG_GLOBAL=l)}try{const l=(0,external_path_.join)((0,external_os_.homedir)(),".myhi","gateway.json");if((0,external_fs_.existsSync)(l)){const n=JSON.parse((0,external_fs_.readFileSync)(l,"utf8"));n.baseUrl&&(d.ANTHROPIC_BASE_URL=n.baseUrl),n.apiKey&&(d.ANTHROPIC_API_KEY=n.apiKey)}}catch{}try{applySecretsToEnv(d,this.cwd)}catch{}return d}_buildArgs(){const d=["--output-format","stream-json","--input-format","stream-json","--verbose"];d.push("--append-system-prompt",MYHI_SYSTEM_PROMPT.replace(/\s*\n\s*/g," ").trim());const l=normalizePermissionMode(this.permissionMode);if(l==="bypassPermissions")d.push("--dangerously-skip-permissions");else if(l==="plan")d.push("--permission-mode","plan"),d.push("--allowedTools","WebSearch"),d.push("--allowedTools","WebFetch");else if(l==="acceptEdits"){d.push("--permission-mode","acceptEdits");const n=["Bash(git *)","Bash(npm *)","Bash(npx *)","Bash(node *)","Bash(ls *)","Bash(cat *)","Bash(mkdir *)","Bash(cp *)","Bash(mv *)","Bash(rm *)","Bash(cd *)","Bash(pwd)","Bash(find *)","Bash(grep *)","Bash(curl *)","Bash(wget *)","Bash(pip *)","Bash(python *)","Bash(python3 *)","Bash(chmod *)","Bash(chown *)","Bash(tar *)","Bash(unzip *)","Bash(zip *)","Bash(sed *)","Bash(awk *)","Bash(head *)","Bash(tail *)","Bash(wc *)","Bash(sort *)","Bash(echo *)","Bash(which *)","Bash(apt *)","Bash(apt-get *)","Bash(docker *)","Bash(ssh *)","Bash(scp *)","Bash(rsync *)","Bash(touch *)","Bash(diff *)","Bash(env *)","Bash(export *)","Bash(source *)","Bash(tee *)","Bash(xargs *)","Bash(du *)","Bash(df *)","Bash(ps *)","Bash(kill *)","Bash(systemctl *)","Bash(journalctl *)","Bash(sudo *)","Task","WebSearch","WebFetch"];for(const e of n)d.push("--allowedTools",e)}return this.modelId&&d.push("--model",this.modelId),this.claudeSessionId&&d.push("--resume",this.claudeSessionId),d}_writeStdin(d){if(!this._proc||!this._proc.stdin?.writable)return!1;try{return this._proc.stdin.write(JSON.stringify(d)+`
|
|
377
377
|
`),!0}catch{return!1}}_spawnProcess(){this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null);const d=findClaude(),l=this._buildArgs(),n=this._buildEnv(),e=d.command,o=[...d.preArgs,...l];console.log(`[agent] \u542F\u52A8\u6301\u4E45\u8FDB\u7A0B: ${e} ${d.preArgs.join(" ")} (\u4F1A\u8BDD: ${this.claudeSessionId||"\u65B0\u5EFA"})`),this._proc=(0,external_child_process_namespaceObject.spawn)(e,o,{cwd:this.cwd,env:n,stdio:["pipe","pipe","pipe"]}),this._buffer="",this._proc.stdout.on("data",(h=>{this._buffer+=h.toString();const c=this._buffer.split(`
|
|
378
378
|
`);this._buffer=c.pop()||"";for(const i of c){const a=i.replace(/\r$/,"");if(a)try{const t=JSON.parse(a);this._handleMessage(t)}catch{a.trim()&&(this.emit("agent:message",{type:"system",subtype:"info",message:a.trim()}),this._checkDeathLoop({type:"system",_raw:a}))}}}));const u=[/connectors are disabled because/i];this._proc.stderr.on("data",(h=>{const c=h.toString().trim();if(!c||c.includes("Warning:")||c.includes("DeprecationWarning"))return;const i=c.split(`
|
|
379
379
|
`).map((t=>t.trim())).filter(Boolean),a=i.filter((t=>!u.some((r=>r.test(t)))));i.length>a.length&&console.log(`[agent:stderr][benign] \u541E\u6389 ${i.length-a.length} \u6761\u826F\u6027\u63D0\u793A`),a.length&&(console.error("[agent:stderr]",a.join(`
|
|
380
380
|
`)),this.emit("agent:error",{message:a.join(`
|
|
381
381
|
`)}),this._checkDeathLoop({type:"stderr",_raw:a.join(`
|
|
382
|
-
`)}))})),this._proc.on("close",(h=>{if(!this._interrupted&&this._buffer.trim())try{const c=JSON.parse(this._buffer.trim());this._handleMessage(c)}catch{}this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._stopStallWatchdog(),this._proc=null,this._buffer="",console.log(`[agent] \u8FDB\u7A0B\u9000\u51FA (code ${h}), \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 ${h})`)),this._pendingResolve=null,this._pendingReject=null)),this._flushPendingSteer(),this.alive&&h!==0&&h!==null&&this.emit("agent:error",{message:`Claude \u8FDB\u7A0B\u5F02\u5E38\u9000\u51FA (code ${h})\uFF0C\u4E0B\u6B21\u67E5\u8BE2\u5C06\u81EA\u52A8\u91CD\u542F`})})),this._proc.on("error",(h=>{this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._stopStallWatchdog(),this._proc=null,this._busy=!1,this.emit("agent:busy",!1),this.emit("agent:error",{message:`\u542F\u52A8 Claude \u5931\u8D25: ${h.message}`}),this._pendingReject&&(this._pendingReject(h),this._pendingResolve=null,this._pendingReject=null)})),this._keepAliveTimer=setInterval((()=>{this._writeStdin({type:"keep_alive"})}),3e4)}async query(d,{internal:l=!1}={}){if(this._busy){this.emit("agent:error",{message:"\u6B63\u5728\u5904\u7406\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u5B8C\u6210"});return}if(l||(this._followCount=0,this._followStopSignal=!1,this._cancelFollowUp()),d==="/clear"){this.reset(),this.emit("agent:message",{type:"system",subtype:"info",message:"\u5DF2\u6E05\u9664 Claude \u4E0A\u4E0B\u6587\uFF0C\u4E0B\u6B21\u63D0\u95EE\u5C06\u5F00\u542F\u5168\u65B0\u5BF9\u8BDD"});return}const n=d.match(/^\/resume\s+(\S+)/);if(n){if(this._proc){try{this._proc.kill("SIGTERM")}catch{}this._proc=null}this.claudeSessionId=n[1],this._history=[],this._buffer="",this._loadResumedHistory(),this.emit("agent:message",{type:"system",subtype:"info",message:`\u5DF2\u5207\u6362\u5230\u4F1A\u8BDD ${n[1].slice(0,8)}...\uFF0C\u4E0B\u6B21\u63D0\u95EE\u5C06\u6062\u590D\u8BE5\u5BF9\u8BDD`});return}const e=d.match(/^\/model\s+(\S+)/);if(e){if(this.modelId=e[1],this._proc){try{this._proc.kill("SIGTERM")}catch{}this._proc=null}this.emit("agent:message",{type:"system",subtype:"info",message:`\u6A21\u578B\u5DF2\u5207\u6362\u4E3A ${e[1]}`});return}if(d==="/plan"||d.startsWith("/plan ")){if(this.permissionMode==="plan"){if(this.permissionMode=normalizePermissionMode(this._prePlanMode),this._prePlanMode=null,this._proc){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){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 h=d.slice(5).trim();if(h){setTimeout((()=>this.query(h)),500);return}}return}if(d.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,l||(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 o=redactDeep(d,this._redactor);return this._history.push({type:"user",content:o,timestamp:Date.now()}),!this.firstUserText&&typeof o=="string"&&!o.startsWith("/")&&(this.firstUserText=o.trim().slice(0,160)),this._proc||this._spawnProcess(),new Promise(((u,h)=>{this._pendingResolve=u,this._pendingReject=h,d.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 ${d} \u5DF2\u53D1\u9001`}),this._pendingResolve&&(this._pendingResolve(0),this._pendingResolve=null,this._pendingReject=null))}),3e4));let c=d;if(this._pseudo?.enabled){const a=this._pseudo.pseudonymize(d);c=a.text;const t=this.claudeSessionId||this.id;saveMap(t,this._pseudoMap),a.count>0&&(appendAudit(t,{ts:Date.now(),level:this._pseudo.level,maskedCount:a.count,byType:a.byType,sentToModel:a.text}),this.emit("agent:message",{type:"system",subtype:"info",message:`\u{1F6E1} \u9690\u79C1\u62A4\u680F\uFF1A\u672C\u8F6E\u5DF2\u8131\u654F ${a.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",message:{role:"user",content:c}})||(this._busy=!1,this.emit("agent:busy",!1),this._pendingResolve=null,this._pendingReject=null,h(new Error("Claude \u8FDB\u7A0B\u4E0D\u53EF\u5199")))}))}_handleMessage(d){const l=!!this.claudeSessionId;if(this._lastActivityAt=Date.now(),d.type==="assistant"&&Array.isArray(d.message?.content)?d.message.content.some((c=>c.type==="tool_use"))&&(this._awaitingTool=!0):d.type==="user"&&(this._awaitingTool=!1),d.session_id&&!this.claudeSessionId&&(this.claudeSessionId=d.session_id),d.type==="system"&&d.subtype==="init"&&d.session_id&&(this.claudeSessionId=d.session_id),!l&&this.claudeSessionId&&this.emit("session-id",this.claudeSessionId),d.type==="system"&&d.subtype==="init"&&this.permissionMode==="bypassPermissions"&&d.permissionMode&&d.permissionMode!=="bypassPermissions"){const c=d.permissionMode;this.reset(),this.emit("agent:message",{type:"system",subtype:"warning",message:`\u26A0\uFE0F \u8FD9\u4E2A\u4F1A\u8BDD\u88AB --resume \u5E26\u56DE\u4E86\u300C${c}\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 n=this._pseudo?.enabled?redactDeep(d,this._pseudo.restore):d,e=redactDeep(n,this._redactor),o=stripHeavyPayload({...e,timestamp:Date.now()}),u=JSON.stringify(o);this._followEnabled&&u.includes("[\u8DDF\u8FDB\u5B8C\u6210]")&&(this._followStopSignal=!0),u.length>10240&&(o._truncated=!0),this._history.push(o);const h=500;if(this._history.length>h&&(this._history=this._history.slice(-h)),this.emit("agent:message",e),this._trackImagePressure(u),this._checkDeathLoop(d,u),d.type==="rate_limit_event"&&d.rate_limit_info&&(this._usage.rateLimitInfo=d.rate_limit_info),d.type==="result"&&(this._usage.queryCount++,d.total_cost_usd&&(this._usage.totalCostUSD+=d.total_cost_usd),d.usage&&(this._usage.totalInputTokens+=d.usage.input_tokens||0,this._usage.totalOutputTokens+=d.usage.output_tokens||0,this._usage.totalCacheReadTokens+=d.usage.cache_read_input_tokens||0,this._usage.totalCacheCreationTokens+=d.usage.cache_creation_input_tokens||0),d.modelUsage))for(const[c,i]of Object.entries(d.modelUsage))this._usage.modelUsage[c]||(this._usage.modelUsage[c]={inputTokens:0,outputTokens:0,costUSD:0}),this._usage.modelUsage[c].inputTokens+=i.inputTokens||0,this._usage.modelUsage[c].outputTokens+=i.outputTokens||0,this._usage.modelUsage[c].costUSD+=i.costUSD||0;if(d.type==="result"){this._slashTimeout&&(clearTimeout(this._slashTimeout),this._slashTimeout=null),this._stopStallWatchdog();const c=!this._interrupted&&!d.is_error;this._busy=!1,this._interrupted=!1,this.emit("agent:busy",!1),this._pendingResolve&&(this._pendingResolve(0),this._pendingResolve=null,this._pendingReject=null),this._flushPendingSteer(),c&&this._maybeRelayDraft(),this._maybeScheduleFollowUp()}}_trackImagePressure(d){const l=(d.match(/"type":"image"/g)||[]).length;l&&(this._imageBlockCount+=l,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(d,l){if(this._loopTripped)return;let n=!1;try{const e=l||JSON.stringify(d);if(LOOP_POISON_PHRASES.some((o=>e.includes(o)))){const o=d.type==="assistant",u=e.includes('"type":"image"'),h=e.length<=POISON_MAX_NOTICE_LEN;n=!o&&(u||h)}}catch{}if(n&&(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(d.type==="assistant"&&Array.isArray(d.message?.content)){const e=!!d.parent_tool_use_id,o=d.parent_tool_use_id||"main";for(const u of d.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 h=`${o}:${u.name}:${this._hashInput(u.input)}`,c=(this._loopSigCounts.get(h)||0)+1;if(this._loopSigCounts.set(h,c),c>=LOOP_MAX_IDENTICAL_CALLS){this._tripLoopBreaker(`\u5DE5\u5177\u300C${u.name}\u300D\u5DF2\u7528\u5B8C\u5168\u76F8\u540C\u7684\u53C2\u6570\u8C03\u7528 ${c} \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(d){let l;try{l=JSON.stringify(stripHeavyPayload(d))}catch{l=String(d)}l.length>4096&&(l=l.slice(0,4096));let n=5381;for(let e=0;e<l.length;e++)n=(n<<5)+n+l.charCodeAt(e)|0;return n.toString(36)}_tripLoopBreaker(d){if(this._loopTripped=!0,console.warn("[agent] \u{1F50C} \u6B7B\u5FAA\u73AF\u7194\u65AD:",d),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=d,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${d}`}),this.interrupt()}_flushPendingSteer(){if(!this._pendingSteer)return;const d=this._pendingSteer;this._pendingSteer=null,setTimeout((()=>{!this._busy&&this.alive&&this.query(d,{internal:!0}).catch((()=>{}))}),600)}setFollowUp({enabled:d,intervalMinutes:l}={}){if(typeof d=="boolean"&&(this._followEnabled=d),l!=null){const n=Math.max(1,Math.min(180,Number(l)||15));this._followIntervalMs=Math.round(n*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 d=null;try{d=nextAutoSendDraft(this.id)}catch{return}if(!d)return;try{removeDraft(d.id)}catch{}const l=buildDraftPrompt(d);l.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(d)||l,timestamp:Date.now()}),this.emit("draft-relayed",{id:d.id,sessionId:this.id}),this.lastInputTime=Date.now(),this.query(l).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 d=Date.now()-this._lastActivityAt;if(d>=STALL_WATCHDOG_MS){const l=Math.round(d/1e3);console.warn(`[agent] \u23F1 \u505C\u6446\u770B\u95E8\u72D7\u89E6\u53D1\uFF1A\u7B49\u5F85\u6A21\u578B\u54CD\u5E94\u5DF2 ${l}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 ${l}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)}respondPermission(d,l){return this._writeStdin({type:"control_response",request_id:d,allow:l})}_hardKillTree(d){if(d)try{if(process.platform==="win32")(0,external_child_process_namespaceObject.execSync)(`taskkill /PID ${d} /F /T`,{stdio:"pipe",timeout:5e3});else{try{process.kill(d,"SIGTERM")}catch{}setTimeout((()=>{try{process.kill(d,0)}catch{return}try{process.kill(d,"SIGKILL")}catch{}}),1e3)}}catch{}}interrupt(){if(!this._proc||!this._busy)return;this._interrupted=!0;const d=this._proc.pid,l=this._proc,e=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===l&&(console.log(`[agent] graceful interrupt \u8D85\u65F6\uFF0C\u5F3A\u5236\u7ED3\u675F\u8FDB\u7A0B\u6811 PID ${d}`),this._hardKillTree(d))}),e),this.emit("agent:message",{type:"system",subtype:"interrupted",message:"\u67E5\u8BE2\u5DF2\u4E2D\u65AD"})}kill(){if(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}_loadResumedHistory(){try{const d=(0,external_path_.join)((0,external_os_.homedir)(),".claude","projects");if(!(0,external_fs_.existsSync)(d))return;for(const l of(0,external_fs_.readdirSync)(d,{withFileTypes:!0})){if(!l.isDirectory())continue;const n=(0,external_path_.join)(d,l.name,this.claudeSessionId+".jsonl");if(!(0,external_fs_.existsSync)(n))continue;const e=(0,external_fs_.readFileSync)(n,"utf8").split(`
|
|
383
|
-
`).filter(Boolean),o=e.slice(-20);if(!this.firstUserText)for(const u of e.slice(0,40))try{const h=JSON.parse(u);if(h.type!=="user"&&h.type!=="human")continue;const c=h.message?.content,i=(typeof c=="string"?c:c?.find?.((a=>a.type==="text"))?.text||"").trim();if(!i||i.startsWith("/")||/^(Caveat:|<command-name>|<system-reminder>|<local-command)/.test(i))continue;this.firstUserText=i.slice(0,160);break}catch{}for(const u of o)try{const h=JSON.parse(u);if(h.type==="human"||h.type==="user"&&h.message?.content){const c=typeof h.message.content=="string"?h.message.content:h.message.content.find((i=>i.type==="text"))?.text||"";c&&this._history.push({type:"user",content:c,timestamp:h.timestamp})}else h.type==="assistant"&&h.message?.content
|
|
382
|
+
`)}))})),this._proc.on("close",(h=>{if(!this._interrupted&&this._buffer.trim())try{const c=JSON.parse(this._buffer.trim());this._handleMessage(c)}catch{}this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._stopStallWatchdog(),this._proc=null,this._buffer="",console.log(`[agent] \u8FDB\u7A0B\u9000\u51FA (code ${h}), \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 ${h})`)),this._pendingResolve=null,this._pendingReject=null)),this._flushPendingSteer(),this.alive&&h!==0&&h!==null&&this.emit("agent:error",{message:`Claude \u8FDB\u7A0B\u5F02\u5E38\u9000\u51FA (code ${h})\uFF0C\u4E0B\u6B21\u67E5\u8BE2\u5C06\u81EA\u52A8\u91CD\u542F`})})),this._proc.on("error",(h=>{this._keepAliveTimer&&(clearInterval(this._keepAliveTimer),this._keepAliveTimer=null),this._stopStallWatchdog(),this._proc=null,this._busy=!1,this.emit("agent:busy",!1),this.emit("agent:error",{message:`\u542F\u52A8 Claude \u5931\u8D25: ${h.message}`}),this._pendingReject&&(this._pendingReject(h),this._pendingResolve=null,this._pendingReject=null)})),this._keepAliveTimer=setInterval((()=>{this._writeStdin({type:"keep_alive"})}),3e4)}async query(d,{internal:l=!1}={}){if(this._busy){this.emit("agent:error",{message:"\u6B63\u5728\u5904\u7406\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u5B8C\u6210"});return}if(l||(this._followCount=0,this._followStopSignal=!1,this._cancelFollowUp()),d==="/clear"){this.reset(),this.emit("agent:message",{type:"system",subtype:"info",message:"\u5DF2\u6E05\u9664 Claude \u4E0A\u4E0B\u6587\uFF0C\u4E0B\u6B21\u63D0\u95EE\u5C06\u5F00\u542F\u5168\u65B0\u5BF9\u8BDD"});return}const n=d.match(/^\/resume\s+(\S+)/);if(n){if(this._proc){try{this._proc.kill("SIGTERM")}catch{}this._proc=null}this.claudeSessionId=n[1],this._history=[],this._buffer="",this._loadResumedHistory(),this.emit("agent:message",{type:"system",subtype:"info",message:`\u5DF2\u5207\u6362\u5230\u4F1A\u8BDD ${n[1].slice(0,8)}...\uFF0C\u4E0B\u6B21\u63D0\u95EE\u5C06\u6062\u590D\u8BE5\u5BF9\u8BDD`});return}const e=d.match(/^\/model\s+(\S+)/);if(e){if(this.modelId=e[1],this._proc){try{this._proc.kill("SIGTERM")}catch{}this._proc=null}this.emit("agent:message",{type:"system",subtype:"info",message:`\u6A21\u578B\u5DF2\u5207\u6362\u4E3A ${e[1]}`});return}if(d==="/plan"||d.startsWith("/plan ")){if(this.permissionMode==="plan"){if(this.permissionMode=normalizePermissionMode(this._prePlanMode),this._prePlanMode=null,this._proc){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){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 h=d.slice(5).trim();if(h){setTimeout((()=>this.query(h)),500);return}}return}if(d.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,l||(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 o=redactDeep(d,this._redactor);return this._history.push({type:"user",content:o,timestamp:Date.now()}),!this.firstUserText&&typeof o=="string"&&!o.startsWith("/")&&(this.firstUserText=o.trim().slice(0,160)),this._proc||this._spawnProcess(),new Promise(((u,h)=>{this._pendingResolve=u,this._pendingReject=h,d.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 ${d} \u5DF2\u53D1\u9001`}),this._pendingResolve&&(this._pendingResolve(0),this._pendingResolve=null,this._pendingReject=null))}),3e4));let c=d;if(this._pseudo?.enabled){const a=this._pseudo.pseudonymize(d);c=a.text;const t=this.claudeSessionId||this.id;saveMap(t,this._pseudoMap),a.count>0&&(appendAudit(t,{ts:Date.now(),level:this._pseudo.level,maskedCount:a.count,byType:a.byType,sentToModel:a.text}),this.emit("agent:message",{type:"system",subtype:"info",message:`\u{1F6E1} \u9690\u79C1\u62A4\u680F\uFF1A\u672C\u8F6E\u5DF2\u8131\u654F ${a.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",message:{role:"user",content:c}})||(this._busy=!1,this.emit("agent:busy",!1),this._pendingResolve=null,this._pendingReject=null,h(new Error("Claude \u8FDB\u7A0B\u4E0D\u53EF\u5199")))}))}_handleMessage(d){const l=!!this.claudeSessionId;if(this._lastActivityAt=Date.now(),d.type==="assistant"&&Array.isArray(d.message?.content)?d.message.content.some((c=>c.type==="tool_use"))&&(this._awaitingTool=!0):d.type==="user"&&(this._awaitingTool=!1),d.session_id&&!this.claudeSessionId&&(this.claudeSessionId=d.session_id),d.type==="system"&&d.subtype==="init"&&d.session_id&&(this.claudeSessionId=d.session_id),!l&&this.claudeSessionId&&this.emit("session-id",this.claudeSessionId),d.type==="system"&&d.subtype==="init"&&this.permissionMode==="bypassPermissions"&&d.permissionMode&&d.permissionMode!=="bypassPermissions"){const c=d.permissionMode;this.reset(),this.emit("agent:message",{type:"system",subtype:"warning",message:`\u26A0\uFE0F \u8FD9\u4E2A\u4F1A\u8BDD\u88AB --resume \u5E26\u56DE\u4E86\u300C${c}\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 n=this._pseudo?.enabled?redactDeep(d,this._pseudo.restore):d,e=redactDeep(n,this._redactor),o=stripHeavyPayload({...e,timestamp:Date.now()}),u=JSON.stringify(o);this._followEnabled&&u.includes("[\u8DDF\u8FDB\u5B8C\u6210]")&&(this._followStopSignal=!0),u.length>10240&&(o._truncated=!0),this._history.push(o);const h=500;if(this._history.length>h&&(this._history=this._history.slice(-h)),this.emit("agent:message",e),this._trackImagePressure(u),this._checkDeathLoop(d,u),d.type==="rate_limit_event"&&d.rate_limit_info&&(this._usage.rateLimitInfo=d.rate_limit_info),d.type==="result"&&(this._usage.queryCount++,d.total_cost_usd&&(this._usage.totalCostUSD+=d.total_cost_usd),d.usage&&(this._usage.totalInputTokens+=d.usage.input_tokens||0,this._usage.totalOutputTokens+=d.usage.output_tokens||0,this._usage.totalCacheReadTokens+=d.usage.cache_read_input_tokens||0,this._usage.totalCacheCreationTokens+=d.usage.cache_creation_input_tokens||0),d.modelUsage))for(const[c,i]of Object.entries(d.modelUsage))this._usage.modelUsage[c]||(this._usage.modelUsage[c]={inputTokens:0,outputTokens:0,costUSD:0}),this._usage.modelUsage[c].inputTokens+=i.inputTokens||0,this._usage.modelUsage[c].outputTokens+=i.outputTokens||0,this._usage.modelUsage[c].costUSD+=i.costUSD||0;{const c=d.type==="assistant"?d.message?.usage:d.type==="result"?d.usage:null;if(c){const i=(c.input_tokens||0)+(c.cache_read_input_tokens||0)+(c.cache_creation_input_tokens||0);i>this._contextTokens&&(this._contextTokens=i)}}if(d.type==="result"){this._slashTimeout&&(clearTimeout(this._slashTimeout),this._slashTimeout=null),this._stopStallWatchdog();const c=!this._interrupted&&!d.is_error;this._busy=!1,this._interrupted=!1,this.emit("agent:busy",!1),this._pendingResolve&&(this._pendingResolve(0),this._pendingResolve=null,this._pendingReject=null),this._flushPendingSteer(),c&&this._maybeRelayDraft(),this._maybeScheduleFollowUp()}}_trackImagePressure(d){const l=(d.match(/"type":"image"/g)||[]).length;l&&(this._imageBlockCount+=l,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(d,l){if(this._loopTripped)return;let n=!1;try{const e=l||JSON.stringify(d);if(LOOP_POISON_PHRASES.some((o=>e.includes(o)))){const o=d.type==="assistant",u=e.includes('"type":"image"'),h=e.length<=POISON_MAX_NOTICE_LEN;n=!o&&(u||h)}}catch{}if(n&&(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(d.type==="assistant"&&Array.isArray(d.message?.content)){const e=!!d.parent_tool_use_id,o=d.parent_tool_use_id||"main";for(const u of d.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 h=`${o}:${u.name}:${this._hashInput(u.input)}`,c=(this._loopSigCounts.get(h)||0)+1;if(this._loopSigCounts.set(h,c),c>=LOOP_MAX_IDENTICAL_CALLS){this._tripLoopBreaker(`\u5DE5\u5177\u300C${u.name}\u300D\u5DF2\u7528\u5B8C\u5168\u76F8\u540C\u7684\u53C2\u6570\u8C03\u7528 ${c} \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(d){let l;try{l=JSON.stringify(stripHeavyPayload(d))}catch{l=String(d)}l.length>4096&&(l=l.slice(0,4096));let n=5381;for(let e=0;e<l.length;e++)n=(n<<5)+n+l.charCodeAt(e)|0;return n.toString(36)}_tripLoopBreaker(d){if(this._loopTripped=!0,console.warn("[agent] \u{1F50C} \u6B7B\u5FAA\u73AF\u7194\u65AD:",d),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=d,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${d}`}),this.interrupt()}_flushPendingSteer(){if(!this._pendingSteer)return;const d=this._pendingSteer;this._pendingSteer=null,setTimeout((()=>{!this._busy&&this.alive&&this.query(d,{internal:!0}).catch((()=>{}))}),600)}setFollowUp({enabled:d,intervalMinutes:l}={}){if(typeof d=="boolean"&&(this._followEnabled=d),l!=null){const n=Math.max(1,Math.min(180,Number(l)||15));this._followIntervalMs=Math.round(n*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 d=null;try{d=nextAutoSendDraft(this.id)}catch{return}if(!d)return;try{removeDraft(d.id)}catch{}const l=buildDraftPrompt(d);l.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(d)||l,timestamp:Date.now()}),this.emit("draft-relayed",{id:d.id,sessionId:this.id}),this.lastInputTime=Date.now(),this.query(l).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 d=Date.now()-this._lastActivityAt;if(d>=STALL_WATCHDOG_MS){const l=Math.round(d/1e3);console.warn(`[agent] \u23F1 \u505C\u6446\u770B\u95E8\u72D7\u89E6\u53D1\uFF1A\u7B49\u5F85\u6A21\u578B\u54CD\u5E94\u5DF2 ${l}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 ${l}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)}respondPermission(d,l){return this._writeStdin({type:"control_response",request_id:d,allow:l})}_hardKillTree(d){if(d)try{if(process.platform==="win32")(0,external_child_process_namespaceObject.execSync)(`taskkill /PID ${d} /F /T`,{stdio:"pipe",timeout:5e3});else{try{process.kill(d,"SIGTERM")}catch{}setTimeout((()=>{try{process.kill(d,0)}catch{return}try{process.kill(d,"SIGKILL")}catch{}}),1e3)}}catch{}}interrupt(){if(!this._proc||!this._busy)return;this._interrupted=!0;const d=this._proc.pid,l=this._proc,e=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===l&&(console.log(`[agent] graceful interrupt \u8D85\u65F6\uFF0C\u5F3A\u5236\u7ED3\u675F\u8FDB\u7A0B\u6811 PID ${d}`),this._hardKillTree(d))}),e),this.emit("agent:message",{type:"system",subtype:"interrupted",message:"\u67E5\u8BE2\u5DF2\u4E2D\u65AD"})}kill(){if(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}_loadResumedHistory(){try{const d=(0,external_path_.join)((0,external_os_.homedir)(),".claude","projects");if(!(0,external_fs_.existsSync)(d))return;for(const l of(0,external_fs_.readdirSync)(d,{withFileTypes:!0})){if(!l.isDirectory())continue;const n=(0,external_path_.join)(d,l.name,this.claudeSessionId+".jsonl");if(!(0,external_fs_.existsSync)(n))continue;const e=(0,external_fs_.readFileSync)(n,"utf8").split(`
|
|
383
|
+
`).filter(Boolean),o=e.slice(-20);if(!this.firstUserText)for(const u of e.slice(0,40))try{const h=JSON.parse(u);if(h.type!=="user"&&h.type!=="human")continue;const c=h.message?.content,i=(typeof c=="string"?c:c?.find?.((a=>a.type==="text"))?.text||"").trim();if(!i||i.startsWith("/")||/^(Caveat:|<command-name>|<system-reminder>|<local-command)/.test(i))continue;this.firstUserText=i.slice(0,160);break}catch{}for(const u of o)try{const h=JSON.parse(u);if(h.type==="human"||h.type==="user"&&h.message?.content){const c=typeof h.message.content=="string"?h.message.content:h.message.content.find((i=>i.type==="text"))?.text||"";c&&this._history.push({type:"user",content:c,timestamp:h.timestamp})}else if(h.type==="assistant"&&h.message?.content){this._history.push({type:"assistant",message:h.message,timestamp:h.timestamp});const c=h.message.usage;if(c){const i=(c.input_tokens||0)+(c.cache_read_input_tokens||0)+(c.cache_creation_input_tokens||0);i>this._contextTokens&&(this._contextTokens=i)}}else h.type==="result"&&this._history.push({type:"result",total_cost_usd:h.costUSD||h.total_cost_usd,timestamp:h.timestamp})}catch{}try{const u=(0,external_fs_.statSync)(n).mtimeMs;u>0&&(this._lastActivityAt=Math.max(this._lastActivityAt,u))}catch{}return}}catch(d){console.warn("[agent] \u52A0\u8F7D\u6062\u590D\u4F1A\u8BDD\u5386\u53F2\u5931\u8D25:",d.message)}}get isBusy(){return this._busy}getRecentHistory(d=20){return this._history.slice(-d)}getUsage(){return{...this._usage}}addViewer(d,l){this._viewers.add(d),l&&this._viewerNames.set(d,l)}removeViewer(d){this._viewers.delete(d),this._viewerNames.delete(d)}get viewerCount(){return new Set(this._viewerNames.values()).size||this._viewers.size}takeControl(d,l){this.controlHolder=d,this.controlHolderName=l||null,this.lastInputTime=Date.now()}releaseControl(){this.controlHolder=null,this.controlHolderName=null,this.lastInputTime=null}isController(d){return this.controlHolder===d}setPermissionMode(d){this.permissionMode=normalizePermissionMode(d),this._proc&&(this.kill(),this.alive=!0)}reset(){this._proc&&(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"}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,owner:this.owner,claudeSessionId:this.claudeSessionId,busy:this._busy,usage:this._usage,contextTokens:this._contextTokens,followUp:this.followUpState()}}}function getSessionHealth(S){const d={found:!1,persistedMode:null,poisoned:!1,messageCount:0,transcriptKB:0,imageCount:0,updatedAt:null};if(!S)return d;try{const l=(0,external_path_.join)((0,external_os_.homedir)(),".claude","projects");if(!(0,external_fs_.existsSync)(l))return d;for(const n of(0,external_fs_.readdirSync)(l,{withFileTypes:!0})){if(!n.isDirectory())continue;const e=(0,external_path_.join)(l,n.name,S+".jsonl");if(!(0,external_fs_.existsSync)(e))continue;const o=(0,external_fs_.readFileSync)(e,"utf8"),u=o.split(`
|
|
384
384
|
`).filter(Boolean);let h=null,c=null,i=0;for(const a of u){const t=a.match(/"type":"image"/g);if(t&&(i+=t.length),a.includes("permissionMode"))try{const r=JSON.parse(a);r.type==="user"&&r.permissionMode&&(h=r.permissionMode)}catch{}}try{const a=JSON.parse(u[u.length-1]);a.timestamp&&(c=a.timestamp)}catch{}return{found:!0,persistedMode:h,poisoned:!!(h&&h!=="bypassPermissions"),messageCount:u.length,transcriptKB:Math.round(o.length/1024),imageCount:i,updatedAt:c}}}catch{}return d}let _claudeSessionsCache=null,_claudeSessionsCacheTime=0;const CLAUDE_SESSIONS_CACHE_TTL=3e4;function listLocalClaudeSessions(S){const d=Date.now();if(_claudeSessionsCache&&d-_claudeSessionsCacheTime<CLAUDE_SESSIONS_CACHE_TTL){if(!S)return _claudeSessionsCache;const o=(0,external_path_.resolve)((0,external_path_.normalize)(S)).replace(/[\\/]+$/,"");return _claudeSessionsCache.filter((u=>(0,external_path_.resolve)((0,external_path_.normalize)(u.projectPath)).replace(/[\\/]+$/,"").startsWith(o)))}const l=[],n=S?(0,external_path_.resolve)((0,external_path_.normalize)(S)).replace(/[\\/]+$/,""):null;try{const o=(0,external_path_.join)((0,external_os_.homedir)(),".claude","projects");if(!(0,external_fs_.existsSync)(o))return l;for(const u of(0,external_fs_.readdirSync)(o,{withFileTypes:!0})){if(!u.isDirectory())continue;const h=(0,external_path_.join)(o,u.name);try{for(const c of(0,external_fs_.readdirSync)(h)){if(!c.endsWith(".jsonl"))continue;const i=c.replace(".jsonl",""),a=(0,external_path_.join)(h,c);try{const t=(0,external_fs_.readFileSync)(a,"utf8").split(`
|
|
385
385
|
`).filter(Boolean);let r=null,p=null,f=0,s="";for(const m of t)try{const b=JSON.parse(m);if(r||(r=b),p=b,f++,!s&&b.type==="human"||b.type==="user"&&b.message?.content){const _=b.message.content;if(typeof _=="string")s=_.slice(0,120);else if(Array.isArray(_)){const g=_.find((w=>w.type==="text"));g&&(s=g.text?.slice(0,120)||"")}}}catch{}let v=u.name;if(process.platform==="win32"&&/^[A-Za-z]--/.test(v)?v=v[0]+":\\"+v.slice(3).replace(/-/g,"\\"):v.startsWith("-")&&(v=v.replace(/-/g,"/")),n&&!(0,external_path_.resolve)((0,external_path_.normalize)(v)).replace(/[\\/]+$/,"").startsWith(n))continue;l.push({sessionId:i,projectDir:u.name,projectPath:v,messageCount:f,summary:s,createdAt:r?.timestamp||null,updatedAt:p?.timestamp||null})}catch{}}}catch{}}}catch{}l.sort(((o,u)=>new Date(u.updatedAt||0).getTime()-new Date(o.updatedAt||0).getTime()));const e=l.slice(0,50);return _claudeSessionsCache=e,_claudeSessionsCacheTime=Date.now(),e.slice(0,20)}const DEFAULT_SHELL=process.platform==="win32"?process.env.SHELL||"powershell.exe":process.env.SHELL||"/bin/bash",sessions_CONFIG_DIR=(0,external_path_.join)((0,external_os_.homedir)(),".myhi"),SESSIONS_FILE=(0,external_path_.join)(sessions_CONFIG_DIR,"sessions.json"),savePath=null;function loadSavedConfigs(){let S;try{S=(0,external_fs_.readFileSync)(SESSIONS_FILE,"utf8")}catch{return[]}try{const d=JSON.parse(S);if(!Array.isArray(d))throw new Error("\u5185\u5BB9\u4E0D\u662F\u6570\u7EC4");return d}catch{const d=new Date().toISOString().replace(/[:.]/g,"-");try{(0,external_fs_.copyFileSync)(SESSIONS_FILE,SESSIONS_FILE+".corrupt-"+d)}catch{}console.error(`[sessions] \u26A0 sessions.json \u635F\u574F\uFF08\u65AD\u7535\u6495\u88C2\u5199/\u88AB\u6539\u574F\uFF09\uFF0C\u5DF2\u7559\u8BC1 sessions.json.corrupt-${d}`);try{const l=JSON.parse((0,external_fs_.readFileSync)(SESSIONS_FILE+".bak","utf8"));if(Array.isArray(l)&&l.length)return console.log(`[sessions] \u2714 \u5DF2\u4ECE .bak \u6062\u590D ${l.length} \u6761\u4F1A\u8BDD\u914D\u7F6E`),l}catch{}return console.error("[sessions] \u26A0 \u65E0 .bak \u53EF\u6062\u590D\uFF0C\u672C\u6B21\u542F\u52A8\u4F1A\u8BDD\u5217\u8868\u4E3A\u7A7A\uFF08\u78C1\u76D8\u8BC1\u636E\u5DF2\u7559\u6863\uFF09"),[]}}function writeSavedConfigs(S){try{(0,external_fs_.mkdirSync)(sessions_CONFIG_DIR,{recursive:!0});try{const l=(0,external_fs_.readFileSync)(SESSIONS_FILE,"utf8").trim();(!S||!S.length)&&l&&l!=="[]"&&console.error(`[sessions] \u26A0 \u5373\u5C06\u7528\u7A7A\u5217\u8868\u8986\u76D6 ${l.length} \u5B57\u8282\u7684\u5B58\u91CF\u4F1A\u8BDD\u6570\u636E\uFF08\u82E5\u975E\u672C\u4EBA\u6E05\u7A7A\u4F1A\u8BDD\uFF0C\u7ACB\u5373\u505C\u6B62 myhi \u5E76\u627E\u56DE .bak\uFF09`)}catch{}try{(0,external_fs_.copyFileSync)(SESSIONS_FILE,SESSIONS_FILE+".bak")}catch{}const d=SESSIONS_FILE+".tmp";(0,external_fs_.writeFileSync)(d,JSON.stringify(S,null,2),{mode:384});try{(0,external_fs_.renameSync)(d,SESSIONS_FILE)}catch{(0,external_fs_.copyFileSync)(d,SESSIONS_FILE);try{(0,external_fs_.rmSync)(d,{force:!0})}catch{}}}catch(d){console.error("[sessions] \u6301\u4E45\u5316\u5199\u5165\u5931\u8D25:",d.message)}}class Session extends external_events_.EventEmitter{constructor(d,l={}){super(),this.id=d,this.createdAt=l.createdAt||new Date().toISOString(),this.title=l.title||DEFAULT_SHELL,this.cwd=l.cwd||process.env.MYHI_CWD||process.cwd(),this.tags=Array.isArray(l.tags)?l.tags:[],this.initCmd=l.initCmd||null,this.owner=l.owner||null,this.cols=l.cols||120,this.rows=l.rows||30,this._lastActivityAt=l.lastActivityAt||0,this._viewers=new Set,this._viewerNames=new Map,this.controlHolder=null,this.controlHolderName=null,this.lastInputTime=null;const n={...process.env};if(delete n.CLAUDECODE,delete n.CLAUDE_CODE_ENTRYPOINT,delete n.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC,l.userDir){const o=(0,external_path_.join)(l.userDir,".gitconfig");(0,external_fs_.existsSync)(o)&&(n.GIT_CONFIG_GLOBAL=o)}this._pty=external_node_pty_namespaceObject.spawn(DEFAULT_SHELL,[],{name:"xterm-256color",cols:this.cols,rows:this.rows,cwd:this.cwd,env:n,useConpty:!1}),this._scrollback="";const e=100*1024;if(this._pty.onData((o=>{this.emit("data",o),this._scrollback+=o,this._scrollback.length>e&&(this._scrollback=this._scrollback.slice(this._scrollback.length-e))})),this._pty.onExit((({exitCode:o})=>{this.exitCode=o,this.emit("exit",o)})),l.initCmd){const o=l.initCmd;let u=!1;const h=c=>{!u&&/[$>#\]]\s*$/.test(c.trimEnd())&&(u=!0,this._pty.off("data",h),setTimeout((()=>this._pty.write(o+"\r")),120))};this._pty.onData(h),setTimeout((()=>{u||(u=!0,this._pty.write(o+"\r"))}),3e3)}}write(d){d!=null&&(this._lastActivityAt=Date.now(),this._pty.write(d))}resize(d,l){this.cols=d,this.rows=l,this._pty.resize(d,l)}kill(){try{this._pty.kill()}catch{}}addViewer(d,l){this._viewers.add(d),l&&this._viewerNames.set(d,l)}removeViewer(d){this._viewers.delete(d),this._viewerNames.delete(d)}get viewerCount(){return new Set(this._viewerNames.values()).size||this._viewers.size}takeControl(d,l){this.controlHolder=d,this.controlHolderName=l||null,this.lastInputTime=Date.now()}releaseControl(){this.controlHolder=null,this.controlHolderName=null,this.lastInputTime=null}isController(d){return this.controlHolder===d}toJSON(){return{id:this.id,title:this.title,cwd:this.cwd,tags:this.tags,createdAt:this.createdAt,lastActivityAt:this._lastActivityAt||null,cols:this.cols,rows:this.rows,viewers:this.viewerCount,alive:this.exitCode===void 0,controlHolder:this.controlHolder,controlHolderName:this.controlHolderName,owner:this.owner}}}class SessionManager{constructor(){this._sessions=new Map,this._agentSessions=new Map;const d=loadSavedConfigs();let l=0;for(const n of d)try{if(n.mode==="agent")if(n.claudeSessionId){const e=(0,external_crypto_.randomUUID)(),o=new AgentSession(e,{...n,resumeSessionId:n.claudeSessionId});o.on("session-id",(()=>this._persist())),this._agentSessions.set(e,o),l++,console.log(`[\u4F1A\u8BDD] \u6062\u590D Agent "${n.title}" (claude: ${n.claudeSessionId.slice(0,8)}...)`)}else console.warn(`[\u4F1A\u8BDD] \u8DF3\u8FC7 "${n.title}"\uFF1Aagent \u4F1A\u8BDD\u65E0 claudeSessionId\uFF08\u4ECE\u672A\u53D1\u8D77\u8FC7\u67E5\u8BE2\uFF09\uFF0C\u65E0\u6CD5\u6062\u590D`);else this._spawn((0,external_crypto_.randomUUID)(),n,!1),l++}catch(e){console.warn(`[\u4F1A\u8BDD] \u6062\u590D "${n.title}" \u5931\u8D25:`,e.message)}d.length&&!l&&console.error(`[\u4F1A\u8BDD] \u26A0 \u78C1\u76D8\u4E0A\u6709 ${d.length} \u6761\u4F1A\u8BDD\u914D\u7F6E\u4F46\u4E00\u6761\u90FD\u6CA1\u6062\u590D\u6210\u529F \u2014\u2014 \u68C0\u67E5\u4E0A\u65B9\u65E5\u5FD7\uFF1Bsessions.json.bak \u91CC\u6709\u4E00\u4EFD\u597D\u6570\u636E`)}_spawn(d,l,n=!0){const e=new Session(d,l);return this._sessions.set(d,e),e.on("exit",(()=>{setTimeout((()=>this._sessions.delete(d)),300*1e3)})),n&&this._persist(),e}create(d={}){return this._spawn((0,external_crypto_.randomUUID)(),d,!0)}createAgent(d={}){const l=(0,external_crypto_.randomUUID)(),n=new AgentSession(l,d);return this._agentSessions.set(l,n),n.on("session-id",(()=>this._persist())),this._persist(),n}get(d){return this._sessions.get(d)||this._agentSessions.get(d)}list(d,l=!1){let n=[...this._sessions.values()].map((o=>({...o.toJSON(),mode:"pty"}))),e=[...this._agentSessions.values()].map((o=>o.toJSON()));return d&&!l&&(n=n.filter((o=>!o.owner||o.owner===d)),e=e.filter((o=>!o.owner||o.owner===d))),[...n,...e]}listSessions(){return[...this._sessions.values(),...this._agentSessions.values()]}kill(d){const l=this._sessions.get(d);if(l){l.kill(),this._sessions.delete(d),this._persist();return}const n=this._agentSessions.get(d);n&&(n.kill(),this._agentSessions.delete(d),this._persist())}persist(){this._persist()}_persist(){const d=[...this._sessions.values()].filter((n=>n.exitCode===void 0)).map((n=>({mode:"pty",title:n.title,cwd:n.cwd,tags:n.tags?.length?n.tags:void 0,createdAt:n.createdAt||void 0,lastActivityAt:n._lastActivityAt||void 0,initCmd:n.initCmd||void 0,owner:n.owner||void 0}))),l=[...this._agentSessions.values()].filter((n=>n.alive)).map((n=>({mode:"agent",title:n.title,firstUserText:n.firstUserText||void 0,cwd:n.cwd,tags:n.tags?.length?n.tags:void 0,createdAt:n.createdAt||void 0,lastActivityAt:n._lastActivityAt||void 0,owner:n.owner||void 0,userDir:n.userDir||void 0,claudeSessionId:n.claudeSessionId||void 0})));writeSavedConfigs([...d,...l])}}const roles_CONFIG_DIR=(0,external_path_.join)((0,external_os_.homedir)(),".myhi"),ROLES_FILE=(0,external_path_.join)(roles_CONFIG_DIR,"roles.json"),USERS_FILE=(0,external_path_.join)(roles_CONFIG_DIR,"users.json"),ROLE_LEVELS={admin:3,operator:2,viewer:1};let rolesConfig=null,usersConfig=null;function loadRoles(){try{if((0,external_fs_.existsSync)(ROLES_FILE))return rolesConfig=JSON.parse((0,external_fs_.readFileSync)(ROLES_FILE,"utf8")),rolesConfig}catch(S){console.warn("[\u89D2\u8272] \u52A0\u8F7D roles.json \u5931\u8D25:",S.message)}return rolesConfig=null,null}function lookupPassword(S){if(!rolesConfig?.passwords)return null;const d=rolesConfig.passwords[S];return d?{name:d.name||"\u7528\u6237",role:d.role||"viewer"}:null}function hasPermission(S,d){return(ROLE_LEVELS[S]||0)>=(ROLE_LEVELS[d]||0)}function isMultiUserMode(){return rolesConfig!==null&&rolesConfig.passwords&&Object.keys(rolesConfig.passwords).length>0}function getDefaultRole(){return rolesConfig?.defaultRole||"admin"}function loadUsers(){try{if((0,external_fs_.existsSync)(USERS_FILE))return usersConfig=JSON.parse((0,external_fs_.readFileSync)(USERS_FILE,"utf8")),usersConfig}catch(S){console.warn("[\u7528\u6237] \u52A0\u8F7D users.json \u5931\u8D25:",S.message)}return usersConfig=null,null}function hasUsers(){return usersConfig!==null&&usersConfig.users&&Object.keys(usersConfig.users).length>0}function isExclusiveMode(){return hasUsers()&&usersConfig.exclusive===!0}function setExclusiveMode(S){usersConfig||(usersConfig={users:{}}),usersConfig.exclusive=!!S,_writeUsers()}function lookupUser(S){if(!usersConfig?.users)return null;const d=usersConfig.users[S];return d?{name:d.name||"\u7528\u6237",dir:d.dir}:null}function listUsers(){return usersConfig?.users?Object.entries(usersConfig.users).map((([S,d])=>({password:S.slice(0,2)+"*".repeat(S.length-2),name:d.name,dir:d.dir}))):[]}function addUser(S,d,l){usersConfig||(usersConfig={users:{}}),usersConfig.users||(usersConfig.users={}),usersConfig.users[S]={name:d,dir:l},_writeUsers()}function removeUser(S){return!usersConfig?.users||!usersConfig.users[S]?!1:(delete usersConfig.users[S],_writeUsers(),!0)}function _writeUsers(){(0,external_fs_.mkdirSync)(roles_CONFIG_DIR,{recursive:!0}),(0,external_fs_.writeFileSync)(USERS_FILE,JSON.stringify(usersConfig,null,2),{mode:384})}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 HOST=process.env.HOST||"0.0.0.0",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 S=(0,external_path_.join)(server_configDir,"cert.pem"),d=(0,external_path_.join)(server_configDir,"key.pem");if((0,external_fs_.existsSync)(S)&&(0,external_fs_.existsSync)(d))try{return{cert:(0,external_fs_.readFileSync)(S),key:(0,external_fs_.readFileSync)(d)}}catch{}try{const l=selfsigned.generate([{name:"commonName",value:"myhi"}],{days:3650,keySize:2048});return(0,external_fs_.writeFileSync)(S,l.cert,"utf8"),(0,external_fs_.writeFileSync)(d,l.private,"utf8"),console.log("[myhi] \u81EA\u7B7E\u540D HTTPS \u8BC1\u4E66\u5DF2\u751F\u6210"),{cert:l.cert,key:l.private}}catch{}try{return(0,external_child_process_namespaceObject.execSync)(`openssl req -x509 -newkey rsa:2048 -keyout "${d}" -out "${S}" -days 3650 -nodes -subj "/CN=myhi"`,{stdio:"pipe",timeout:1e4}),{cert:(0,external_fs_.readFileSync)(S),key:(0,external_fs_.readFileSync)(d)}}catch(l){return console.warn(`[myhi] \u751F\u6210 HTTPS \u8BC1\u4E66\u5931\u8D25: ${l.message?.split(`
|
|
386
386
|
`)[0]||l}`),null}}const pidFile=(0,external_path_.join)(server_configDir,"server.pid"),daemonPidFile=(0,external_path_.join)(server_configDir,"daemon.pid"),IS_DAEMON_CHILD=!!process.env.MYHI_DAEMON;function killOldProcess(S,d){let l=!1;try{process.kill(S,0),l=!0}catch{}if(!l)return!0;console.log(`[myhi] \u68C0\u6D4B\u5230\u5DF2\u8FD0\u884C\u7684${d} (PID ${S})\uFF0C\u6B63\u5728\u505C\u6B62...`);try{process.platform==="win32"?(0,external_child_process_namespaceObject.execSync)(`taskkill /PID ${S} /F /T`,{stdio:"pipe",timeout:5e3}):process.kill(S,"SIGTERM")}catch{}const n=Date.now()+5e3;for(;Date.now()<n;){try{process.kill(S,0)}catch{return!0}const o=Date.now()+200;for(;Date.now()<o;);}let e=!1;try{process.kill(S,0),e=!0}catch{}return!e}(function S(){try{const d=parseInt((0,external_fs_.readFileSync)(daemonPidFile,"utf8").trim(),10);if(d&&d!==process.pid&&d!==parseInt(process.env.MYHI_DAEMON_PID||"0",10)){let l=!1;try{process.kill(d,0),l=!0}catch{}if(l&&!IS_DAEMON_CHILD){console.log("[myhi] \u68C0\u6D4B\u5230\u540E\u53F0 daemon \u5728\u8FD0\u884C\uFF0C\u5148\u505C\u6B62..."),killOldProcess(d,"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 d=parseInt((0,external_fs_.readFileSync)(pidFile,"utf8").trim(),10);d&&d!==process.pid&&(killOldProcess(d,"\u5B9E\u4F8B")||(console.error(`[myhi] \u65E0\u6CD5\u505C\u6B62\u65E7\u8FDB\u7A0B (PID ${d})\uFF0C\u8BF7\u624B\u52A8\u6267\u884C\uFF1A`),console.error(" myhi stop"),console.error(` \u6216: ${process.platform==="win32"?`taskkill /PID ${d} /F`:`kill -9 ${d}`}`),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 S of manager.listSessions())try{S.kill()}catch{}}}catch{}cleanupPid()}process.on("exit",cleanupPid),process.on("SIGTERM",(()=>{gracefulShutdown(),process.exit(0)})),process.on("SIGINT",(()=>{gracefulShutdown(),process.exit(0)}));const RECOVERABLE_ERRNO=new Set(["ECONNRESET","EPIPE","ECONNABORTED","ETIMEDOUT","ENOENT","EBUSY","EACCES","EPERM","EISDIR","ERR_STREAM_PREMATURE_CLOSE","ERR_STREAM_DESTROYED","ERR_HTTP_HEADERS_SENT"]);process.on("uncaughtException",(S=>{if(RECOVERABLE_ERRNO.has(S?.code)){console.error(`[myhi] \u5DF2\u5FFD\u7565\u53EF\u6062\u590D\u5F02\u5E38(${S.code}):`,S.message);return}console.error("[myhi] \u672A\u6355\u83B7\u5F02\u5E38:",S.message),gracefulShutdown(),process.exit(1)})),process.on("unhandledRejection",(S=>{console.error("[myhi] \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD:",S)}));function readOrCreate(S,d){try{if((0,external_fs_.existsSync)(S))return(0,external_fs_.readFileSync)(S,"utf8").trim()}catch{}const l=d();return(0,external_fs_.writeFileSync)(S,l,{mode:384}),l}const TOKEN=readOrCreate((0,external_path_.join)(server_configDir,"token"),(()=>(0,external_crypto_.randomBytes)(16).toString("hex")));let PASSWORD=readOrCreate((0,external_path_.join)(server_configDir,"password"),(()=>String(Math.floor(1e3+Math.random()*9e3))));loadRoles(),loadUsers();let activeUser=null;const userSessions=new Map;userSessions.set(TOKEN,{role:"admin",name:"\u7BA1\u7406\u5458",permanent:!0});const SESSION_MAX_AGE=10080*60*1e3;setInterval((()=>{const S=Date.now();for(const[d,l]of userSessions)l.permanent||(!l.lastUsed||S-l.lastUsed>SESSION_MAX_AGE)&&userSessions.delete(d)}),3600*1e3);function getTailscaleIP(){try{return(0,external_child_process_namespaceObject.execSync)("tailscale ip -4",{timeout:3e3,stdio:"pipe"}).toString().trim().split(`
|
package/package.json
CHANGED