@yuandc/aica 0.1.76 → 0.1.78

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.
@@ -0,0 +1 @@
1
+ import p from"node:fs";import{closeAcpProcess as C}from"../../client/acp-process.js";import{JsonLineRpcClient as A}from"../../client/json-rpc.js";import{startCodexAppServer as I}from"./codex-process.js";import{buildCodexSessionImport as T}from"./session-import.js";const i=t=>t&&typeof t=="object"&&!Array.isArray(t)?t:{},s=t=>typeof t=="string"?t:"";function u(t){const o=p.realpathSync(t);if(!p.statSync(o).isDirectory())throw new Error("项目工作目录不存在。");return process.platform==="win32"?o.toLowerCase():o}async function v(t,o){const c=u(t.rootPath);if(t.action==="list"){const e=i(await o("thread/list",{cwd:[...new Set([t.rootPath,p.realpathSync(t.rootPath)])],limit:30,cursor:t.cursor||null,searchTerm:t.search?.trim()||null,modelProviders:[],sourceKinds:["cli","vscode","appServer","exec","unknown"],sortKey:"updated_at",sortDirection:"desc",archived:!1}));return{items:(Array.isArray(e.data)?e.data:[]).map(i).filter(n=>{try{return w(n)&&u(s(n.cwd))===c}catch{return!1}}).map(n=>({id:s(n.id),title:(s(n.name)||s(n.preview)||"未命名会话").slice(0,120),preview:s(n.preview).slice(0,240),updatedAt:Number(n.updatedAt)||0,source:typeof n.source=="string"?n.source:"unknown"})),nextCursor:s(e.nextCursor)||null}}if(!t.threadId)throw new Error("缺少 Codex 会话 ID。");const r=i(i(await o("thread/read",{threadId:t.threadId,includeTurns:!1})).thread);if(s(r.id)!==t.threadId||!w(r))throw new Error("该会话不可从外部导入。");if(u(s(r.cwd))!==c)throw new Error("会话工作目录与当前项目不一致。");if(t.action==="extract"&&(i(r.status).type==="active"||r.canAcceptDirectInput===!1))throw new Error("会话正在使用中或不接受直接输入,请先在原客户端结束任务后重试。");const d=i(await o("thread/turns/list",{threadId:t.threadId,limit:t.action==="extract"?20:5,cursor:t.action==="preview"&&t.cursor||null,sortDirection:"desc",itemsView:"summary"})),m=Array.isArray(d.data)?d.data:[];if(t.action==="extract"&&m.some(e=>["inProgress","in_progress"].includes(s(i(e).status))))throw new Error("该会话仍有任务运行中,请等待完成后导入。");const l=T({thread:r,turns:m},{sessionId:t.threadId,turnLimit:t.action==="extract"?20:5,detailMode:"standard",diffEnabled:!1});return t.action==="extract"?l:{turns:l.turns.map(e=>({id:e.sourceTurnId,atMs:e.startedAtMs,userText:e.userText.slice(0,12e3),assistantText:e.assistantText.slice(0,12e3),truncated:e.userText.length>12e3||e.assistantText.length>12e3})),nextCursor:s(d.nextCursor)||null,truncated:l.truncated}}function w(t){return!!s(t.id)&&!t.parentThreadId&&!t.ephemeral&&t.threadSource!=="aca"&&!i(t.source).subAgent}let a=null,f,x=Promise.resolve();function P(t){const o=x.then(async()=>{clearTimeout(f);try{if(!a||a.started.child.exitCode!==null||a.started.child.signalCode!==null){const r=I(process.cwd());a={started:r,rpc:new A(r.child,{peerName:"Codex history"})},await a.rpc.request("initialize",{clientInfo:{name:"aica-external-sessions",version:"0.1.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}},2e4)}const c=a.rpc;return await v(t,(r,d)=>c.request(r,d,2e4))}catch(c){throw await h(),c}finally{f=setTimeout(()=>{h()},15e3),f.unref()}});return x=o.catch(()=>{}),o}async function h(){const t=a;a=null,t&&await C(t.started.child).catch(()=>{})}export{u as canonicalCodexDirectory,P as queryExternalCodexSessions,v as readExternalCodexSessions};
@@ -1,2 +1,2 @@
1
- import{execFileSync as l}from"node:child_process";import d from"node:fs";import c from"node:path";import h from"node:crypto";const m=50*1024*1024,g=["path","file","filePath","file_path","filename","targetPath","target_path","move_path"];function T(t){if(!b(t))return null;const e=v(t);if(!e)return null;const n=new Map;for(const r of e)n.set(r.path,{status:r.status,objectHash:r.status.includes("D")?null:w(t,r.path)});return n}function R(t){const e=new Map;for(const n of t.evidencePaths)x(e,t.cwd,n,"unknown","acp_tool");return[...e.values()].filter(n=>n.relativePath&&!n.relativePath.startsWith(".git/")).sort((n,r)=>n.relativePath.localeCompare(r.relativePath))}function E(t){const e=new Set;return u(t,(n,r)=>{if(typeof n=="string"&&(S(r)&&p(e,n),r==="command"))for(const s of F(n))p(e,s)}),A(t,e),j(t,e),[...e]}function x(t,e,n,r,s){const a=y(e,n);if(!a)return;const i=t.get(a.relativePath),o=C(a.absolutePath),f={path:a.absolutePath,absolutePath:a.absolutePath,relativePath:a.relativePath,changeType:P(i?.changeType,r),source:i?.source==="acp_tool"||i?.source==="acp_diff"?i.source:s,exists:!!o?.isFile(),downloadable:!!o?.isFile(),...o?.isFile()?{size:o.size,mime:z(a.absolutePath),sha256:o.size<=m?_(a.absolutePath):void 0}:{}};t.set(a.relativePath,f)}function P(t,e){return!t||t==="unknown"?e:e==="unknown"||t===e?t:t==="created"&&e==="modified"?"created":e}function y(t,e){if(!e||e.includes("\0"))return null;const n=c.resolve(t),r=c.isAbsolute(e)?c.resolve(e):c.resolve(n,e),s=c.relative(n,r).replace(/\\/g,"/");return!s||s.startsWith("..")||c.isAbsolute(s)?null:{absolutePath:r,relativePath:s}}function b(t){try{return l("git",["-C",t,"rev-parse","--is-inside-work-tree"],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}),!0}catch{return!1}}function v(t){try{const n=l("git",["-C",t,"status","--porcelain=v1","-z","--untracked-files=all"],{encoding:"buffer",maxBuffer:20971520}).toString("utf8").split("\0").filter(Boolean),r=[];for(let s=0;s<n.length;s+=1){const a=n[s],i=a.slice(0,2),o=a.slice(3);if(o)if(i.startsWith("R")||i.startsWith("C")){const f=n[s+1];f&&(r.push({status:i,path:f}),s+=1)}else r.push({status:i,path:o})}return r}catch{return null}}function w(t,e){try{const n=l("git",["-C",t,"hash-object","--",e],{encoding:"utf8",stdio:["ignore","pipe","ignore"],maxBuffer:1048576}).trim();return/^[0-9a-f]{40,64}$/i.test(n)?n:null}catch{return null}}function u(t,e,n,r=0){if(!(r>8)&&(e(t,n),!(!t||typeof t!="object"))){if(Array.isArray(t)){for(const s of t)u(s,e,void 0,r+1);return}for(const[s,a]of Object.entries(t))u(a,e,s,r+1)}}function A(t,e){u(t,n=>{if(!n||typeof n!="object"||Array.isArray(n))return;const r=n;r.type==="diff"&&p(e,r.path)})}function j(t,e){u(t,(n,r)=>{if(!(r!=="changes"||!n||typeof n!="object"||Array.isArray(n)))for(const s of Object.keys(n))p(e,s)})}function S(t){return t?g.includes(t):!1}function p(t,e){if(typeof e!="string")return;const n=k(e);!n||n.length>500||n.includes(`
2
- `)||n==="."||n===".."||t.add(n)}function k(t){let e=t.trim();e=e.replace(/\s+\+\d+\s*\/\s*-\d+(?:\s+.*)?$/,""),e=e.replace(/\s+\(\s*\+\d+\s*[,/ ]\s*-\d+\s*\)(?:\s+.*)?$/,""),e=e.replace(/\s+(?:source|event|workspace|session|last)=\S+.*$/,"");const n=e.split(/\s+/)[0]||"";return n&&/\.[A-Za-z][A-Za-z0-9+-]{0,12}$/.test(n)&&(e=n),e.replace(/^["']|["']$/g,"").trim()}function F(t){const e=[],n=/(?:^|\s)(?:\d?>|>>)\s*(?:"([^"]+)"|'([^']+)'|([^\s;&|<>]+))/g;let r;for(;r=n.exec(t);){const a=r[1]||r[2]||r[3];a&&e.push(a)}const s=/(?:^|\s)touch\s+(?:"([^"]+)"|'([^']+)'|([^\s;&|<>]+))/g;for(;r=s.exec(t);){const a=r[1]||r[2]||r[3];a&&!a.startsWith("-")&&e.push(a)}return e}function C(t){try{return d.statSync(t)}catch{return null}}function _(t){try{return h.createHash("sha256").update(d.readFileSync(t)).digest("hex")}catch{return}}function z(t){switch(c.extname(t).toLowerCase()){case".doc":return"application/msword";case".xls":return"application/vnd.ms-excel";case".xlsm":return"application/vnd.ms-excel.sheet.macroEnabled.12";case".ppt":return"application/vnd.ms-powerpoint";case".pptx":return"application/vnd.openxmlformats-officedocument.presentationml.presentation";case".odt":return"application/vnd.oasis.opendocument.text";case".ods":return"application/vnd.oasis.opendocument.spreadsheet";case".odp":return"application/vnd.oasis.opendocument.presentation";case".rtf":return"application/rtf";case".svg":return"image/svg+xml";case".bmp":return"image/bmp";case".tif":case".tiff":return"image/tiff";case".avif":return"image/avif";case".pdf":return"application/pdf";case".md":case".markdown":return"text/markdown; charset=utf-8";case".txt":case".log":return"text/plain; charset=utf-8";case".json":return"application/json; charset=utf-8";case".csv":return"text/csv; charset=utf-8";case".png":return"image/png";case".jpg":case".jpeg":return"image/jpeg";case".gif":return"image/gif";case".webp":return"image/webp";case".zip":return"application/zip";case".docx":return"application/vnd.openxmlformats-officedocument.wordprocessingml.document";case".xlsx":return"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";default:return"application/octet-stream"}}export{T as captureGitSnapshot,R as collectAffectedFiles,E as extractAffectedFilePathsFromAcpRaw,z as mimeForPath};
1
+ import{execFileSync as l}from"node:child_process";import d from"node:fs";import c from"node:path";import h from"node:crypto";const m=50*1024*1024,g=["path","file","filePath","file_path","filename","targetPath","target_path","move_path"];function T(t){if(!y(t))return null;const e=b(t);if(!e)return null;const n=new Map;for(const r of e)n.set(r.path,{status:r.status,objectHash:r.status.includes("D")?null:v(t,r.path)});return n}function R(t){const e=new Map;for(const n of t.evidencePaths)x(e,t.cwd,n,"unknown","acp_tool");return[...e.values()].filter(n=>n.relativePath&&!n.relativePath.startsWith(".git/")).sort((n,r)=>n.relativePath.localeCompare(r.relativePath))}function E(t){const e=new Set;return u(t,(n,r)=>{if(typeof n=="string"&&(S(r)&&p(e,n),r==="command"))for(const s of F(n))p(e,s)}),A(t,e),j(t,e),[...e]}function x(t,e,n,r,s){const a=w(e,n);if(!a)return;const i=t.get(a.relativePath),o=C(a.absolutePath),f={path:a.absolutePath,absolutePath:a.absolutePath,relativePath:a.relativePath,changeType:P(i?.changeType,r),source:i?.source==="acp_tool"||i?.source==="acp_diff"?i.source:s,exists:!!o?.isFile(),downloadable:!!o?.isFile(),...o?.isFile()?{size:o.size,mime:_(a.absolutePath),sha256:o.size<=m?H(a.absolutePath):void 0}:{}};t.set(a.relativePath,f)}function P(t,e){return!t||t==="unknown"?e:e==="unknown"||t===e?t:t==="created"&&e==="modified"?"created":e}function w(t,e){if(!e||e.includes("\0"))return null;const n=c.resolve(t),r=c.isAbsolute(e)?c.resolve(e):c.resolve(n,e),s=c.relative(n,r).replace(/\\/g,"/");return!s||s.startsWith("..")||c.isAbsolute(s)?null:{absolutePath:r,relativePath:s}}function y(t){try{return l("git",["-C",t,"rev-parse","--is-inside-work-tree"],{windowsHide:!0,encoding:"utf8",stdio:["ignore","pipe","ignore"]}),!0}catch{return!1}}function b(t){try{const n=l("git",["-C",t,"status","--porcelain=v1","-z","--untracked-files=all"],{windowsHide:!0,encoding:"buffer",maxBuffer:20971520}).toString("utf8").split("\0").filter(Boolean),r=[];for(let s=0;s<n.length;s+=1){const a=n[s],i=a.slice(0,2),o=a.slice(3);if(o)if(i.startsWith("R")||i.startsWith("C")){const f=n[s+1];f&&(r.push({status:i,path:f}),s+=1)}else r.push({status:i,path:o})}return r}catch{return null}}function v(t,e){try{const n=l("git",["-C",t,"hash-object","--",e],{windowsHide:!0,encoding:"utf8",stdio:["ignore","pipe","ignore"],maxBuffer:1048576}).trim();return/^[0-9a-f]{40,64}$/i.test(n)?n:null}catch{return null}}function u(t,e,n,r=0){if(!(r>8)&&(e(t,n),!(!t||typeof t!="object"))){if(Array.isArray(t)){for(const s of t)u(s,e,void 0,r+1);return}for(const[s,a]of Object.entries(t))u(a,e,s,r+1)}}function A(t,e){u(t,n=>{if(!n||typeof n!="object"||Array.isArray(n))return;const r=n;r.type==="diff"&&p(e,r.path)})}function j(t,e){u(t,(n,r)=>{if(!(r!=="changes"||!n||typeof n!="object"||Array.isArray(n)))for(const s of Object.keys(n))p(e,s)})}function S(t){return t?g.includes(t):!1}function p(t,e){if(typeof e!="string")return;const n=k(e);!n||n.length>500||n.includes(`
2
+ `)||n==="."||n===".."||t.add(n)}function k(t){let e=t.trim();e=e.replace(/\s+\+\d+\s*\/\s*-\d+(?:\s+.*)?$/,""),e=e.replace(/\s+\(\s*\+\d+\s*[,/ ]\s*-\d+\s*\)(?:\s+.*)?$/,""),e=e.replace(/\s+(?:source|event|workspace|session|last)=\S+.*$/,"");const n=e.split(/\s+/)[0]||"";return n&&/\.[A-Za-z][A-Za-z0-9+-]{0,12}$/.test(n)&&(e=n),e.replace(/^["']|["']$/g,"").trim()}function F(t){const e=[],n=/(?:^|\s)(?:\d?>|>>)\s*(?:"([^"]+)"|'([^']+)'|([^\s;&|<>]+))/g;let r;for(;r=n.exec(t);){const a=r[1]||r[2]||r[3];a&&e.push(a)}const s=/(?:^|\s)touch\s+(?:"([^"]+)"|'([^']+)'|([^\s;&|<>]+))/g;for(;r=s.exec(t);){const a=r[1]||r[2]||r[3];a&&!a.startsWith("-")&&e.push(a)}return e}function C(t){try{return d.statSync(t)}catch{return null}}function H(t){try{return h.createHash("sha256").update(d.readFileSync(t)).digest("hex")}catch{return}}function _(t){switch(c.extname(t).toLowerCase()){case".doc":return"application/msword";case".xls":return"application/vnd.ms-excel";case".xlsm":return"application/vnd.ms-excel.sheet.macroEnabled.12";case".ppt":return"application/vnd.ms-powerpoint";case".pptx":return"application/vnd.openxmlformats-officedocument.presentationml.presentation";case".odt":return"application/vnd.oasis.opendocument.text";case".ods":return"application/vnd.oasis.opendocument.spreadsheet";case".odp":return"application/vnd.oasis.opendocument.presentation";case".rtf":return"application/rtf";case".svg":return"image/svg+xml";case".bmp":return"image/bmp";case".tif":case".tiff":return"image/tiff";case".avif":return"image/avif";case".pdf":return"application/pdf";case".md":case".markdown":return"text/markdown; charset=utf-8";case".txt":case".log":return"text/plain; charset=utf-8";case".json":return"application/json; charset=utf-8";case".csv":return"text/csv; charset=utf-8";case".png":return"image/png";case".jpg":case".jpeg":return"image/jpeg";case".gif":return"image/gif";case".webp":return"image/webp";case".zip":return"application/zip";case".docx":return"application/vnd.openxmlformats-officedocument.wordprocessingml.document";case".xlsx":return"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";default:return"application/octet-stream"}}export{T as captureGitSnapshot,R as collectAffectedFiles,E as extractAffectedFilePathsFromAcpRaw,_ as mimeForPath};
@@ -0,0 +1 @@
1
+ import{loadAcaConfig as s}from"./aca-config.js";import{canonicalCodexDirectory as c,queryExternalCodexSessions as x}from"../acp/providers/codex/external-sessions.js";import{expandWorkerRuntimePath as i}from"./worker-runtime-paths.js";async function f(e,r){const t=s().projects.find(n=>n.projectId===r.projectId&&n.workspaceId===r.workspaceId);if(!t)throw new Error("当前 Worker 未登记此项目,请刷新项目登记后重试。");const o=i(t.rootPath);if(c(o)!==c(i(String(r.rootPath||""))))throw new Error("项目目录登记已变化,请刷新后重试。");return x({rootPath:o,action:e==="external_codex_list"?"list":e==="external_codex_preview"?"preview":"extract",threadId:String(r.threadId||""),cursor:String(r.cursor||""),search:String(r.search||"")})}export{f as executeExternalCodexOperation};
@@ -1,3 +1,3 @@
1
- import{execFileSync as g}from"node:child_process";import m from"node:os";import{readJsonFile as I,writeJsonFile as v}from"./fs.js";import{getRuntimeStatePath as y}from"./paths.js";import{acaServerRequest as x}from"./aca-server-client.js";import{loadAcaConfig as C}from"./aca-config.js";import{providerHealthSnapshot as w}from"./provider-health.js";import{readCodexCapabilities as O}from"./codex-capabilities.js";import{AICA_VERSION as _}from"../version.js";import{applyProjectSync as k}from"./project-sync.js";const b=3e4,E=360*60*1e3,S=360*60*1e3;let p=null,u=null;async function D(e=C(),t={}){if(!e.token)return{ok:!1,skipped:!0,reason:"not_logged_in"};const o=await x("POST","/api/heartbeat",{machineId:e.machineId,machineName:e.machineName,machineInfo:{platform:m.platform(),architecture:m.arch(),osRelease:m.release(),acaVersion:V(),hostname:m.hostname()},workspaceId:e.defaultWorkspaceId,agentConfigs:t.includeProviderDetails===!1?[]:await N(e),projects:e.projects.map(n=>({projectId:n.projectId,workspaceId:n.workspaceId,name:n.name,rootPath:n.rootPath}))});return k(e,o),o}async function N(e){const t=w(),o=await O(),n=o?.capabilities??j();return[{agentId:`${e.machineId}:builtin:codex`,workspaceId:e.defaultWorkspaceId,name:"Codex",agentType:"codex",cliType:"builtin",machineId:e.machineId,model:o?.defaultModel||"gpt-5.5",mode:"agent-full-access",raw:{providerStatus:t.codex,capabilities:n}},{agentId:`${e.machineId}:builtin:mimo`,workspaceId:e.defaultWorkspaceId,name:"MimoCode",agentType:"mimo",cliType:"builtin",machineId:e.machineId,model:"mimo/mimo-auto",mode:"agent-full-access",raw:{providerStatus:t.mimo,capabilities:H()}},{agentId:`${e.machineId}:builtin:opencode`,workspaceId:e.defaultWorkspaceId,name:"OpenCode",agentType:"opencode",cliType:"builtin",machineId:e.machineId,model:process.env.ACA_OPENCODE_DEFAULT_MODEL||null,mode:"agent-full-access",raw:{providerStatus:t.opencode,capabilities:$()}}]}function V(e=process.env){return e.ACA_VERSION?.trim()||_}function j(){const e=[{id:"read-only",name:"Read-only",description:"Requires approval to edit files and run commands."},{id:"agent",name:"Agent",description:"Read and edit files, and run commands."},{id:"agent-full-access",name:"Agent (full access)",description:"Edit files and run commands with full access."}],t=[{modelId:"gpt-5.5",name:"gpt-5.5",description:"Latest frontier Codex model"},{modelId:"gpt-5.4",name:"gpt-5.4",description:"Frontier Codex model"},{modelId:"gpt-5.4-mini",name:"gpt-5.4-mini",description:"Smaller, faster Codex model"}],o=[{value:"low",name:"Low",description:"Fastest responses"},{value:"medium",name:"Medium",description:"Balanced reasoning"},{value:"high",name:"High",description:"More reasoning for difficult tasks"},{value:"xhigh",name:"X High",description:"Extra reasoning for complex tasks"}];return{source:"aca-static",fetchedAt:Date.now(),contextUsage:!0,contextCompaction:!0,modes:e,models:t,configOptions:[{id:"mode",name:"Mode",category:"mode",type:"select",currentValue:"agent-full-access",options:e.map(n=>({value:n.id,name:n.name,description:n.description}))},{id:"model",name:"Model",category:"model",type:"select",currentValue:"gpt-5.5",options:t.map(n=>({value:n.modelId,name:n.name,description:n.description}))},{id:"reasoning_effort",name:"Reasoning effort",category:"thought_level",type:"select",currentValue:"medium",options:o}]}}function R(){const e=[{id:"agent",name:"Agent",description:"Run MimoCode with normal workspace permissions."},{id:"agent-full-access",name:"Agent (full access)",description:"Run MimoCode and auto-approve supported local permissions."}],t=[{modelId:"mimo/mimo-auto",name:"MiMo Auto (free)",description:"MiMo Auto free model"},{modelId:"xiaomi/mimo-v2.5",name:"mimo-v2.5",description:"MimoCode v2.5"},{modelId:"xiaomi/mimo-v2.5-pro",name:"mimo-v2.5-pro",description:"MimoCode v2.5 Pro"},{modelId:"xiaomi/mimo-v2.5-pro-ultraspeed",name:"mimo-v2.5-pro-ultraspeed",description:"MimoCode v2.5 Pro UltraSpeed"}],o=[{value:"minimal",name:"Minimal",description:"Fastest responses"},{value:"high",name:"High",description:"More reasoning for difficult tasks"},{value:"max",name:"Max",description:"Maximum reasoning when supported"}];return{source:"aca-static",fetchedAt:Date.now(),contextUsage:!0,contextCompaction:!1,modes:e,models:t,configOptions:[{id:"mode",name:"Mode",category:"mode",type:"select",currentValue:"agent-full-access",options:e.map(n=>({value:n.id,name:n.name,description:n.description}))},{id:"model",name:"Model",category:"model",type:"select",currentValue:"mimo/mimo-auto",options:t.map(n=>({value:n.modelId,name:n.name,description:n.description}))},{id:"variant",name:"Variant",category:"thought_level",type:"select",currentValue:"high",options:o}]}}function H(){const e=Date.now();if(p&&p.expiresAtMs>e)return p.capabilities;const t=z()??R();return p={expiresAtMs:e+E,capabilities:t},t}function T(){const e=[{id:"plan",name:"Plan",description:"Inspect the project and propose changes."},{id:"build",name:"Build",description:"Read and edit files, and run commands when approved."},{id:"agent-full-access",name:"Agent (full access)",description:"Run OpenCode with ACA full-access mode mapping."}],t=[{modelId:"",name:"Default",description:"Use the model selected by OpenCode configuration."}];return{source:"aca-static",fetchedAt:Date.now(),contextUsage:!0,contextCompaction:!1,modes:e,models:t,configOptions:[{id:"mode",name:"Mode",category:"mode",type:"select",currentValue:"agent-full-access",options:e.map(o=>({value:o.id,name:o.name,description:o.description}))},{id:"model",name:"Model",category:"model",type:"text",currentValue:process.env.ACA_OPENCODE_DEFAULT_MODEL||"",options:t.map(o=>({value:o.modelId,name:o.name,description:o.description}))}]}}function $(){const e=Date.now();if(u&&u.expiresAtMs>e)return u.capabilities;const t=L()??T();return u={expiresAtMs:e+S,capabilities:t},t}function L(){try{const e=process.env.ACA_OPENCODE_COMMAND||"opencode",t=g(e,["models","--verbose"],{encoding:"utf8",timeout:15e3,maxBuffer:8*1024*1024,stdio:["ignore","pipe","pipe"]}),o=P(t);if(!o.length)return null;const n=[{id:"plan",name:"Plan",description:"Inspect the project and propose changes."},{id:"build",name:"Build",description:"Read and edit files, and run commands when approved."},{id:"agent-full-access",name:"Agent (full access)",description:"Run OpenCode with ACA full-access mode mapping."}],a=F(o);return{source:"opencode-cli",fetchedAt:Date.now(),contextUsage:!0,contextCompaction:!1,modes:n,models:o.map(i=>({modelId:i.modelId,name:i.displayName,description:i.description,metadata:i.metadata})),configOptions:[{id:"mode",name:"Mode",category:"mode",type:"select",currentValue:"agent-full-access",options:n.map(i=>({value:i.id,name:i.name,description:i.description}))},{id:"model",name:"Model",category:"model",type:"select",currentValue:a,options:o.map(i=>({value:i.modelId,name:i.displayName,description:i.description}))}]}}catch{return null}}function P(e){const t=e.split(/\r?\n/),o=[];let n=0;for(;n<t.length;){const a=t[n]?.trim()??"";if(n+=1,!/^[a-z0-9_.-]+\/[a-z0-9_.-]+$/i.test(a))continue;const i=[];let s=0,c=!1;for(;n<t.length;){const d=t[n]??"";if(n+=1,!(!c&&!d.trim().startsWith("{"))&&(c=!0,i.push(d),s+=f(d,"{")-f(d,"}"),c&&s<=0))break}const r=A(i.join(`
2
- `));if(!r)continue;const l=M(r.name,r.id,a)??a;o.push({modelId:a,displayName:U(l,r),description:W(r),metadata:r})}return o}function F(e){const t=process.env.ACA_OPENCODE_DEFAULT_MODEL?.trim();return t&&e.some(o=>o.modelId===t)?t:e.find(o=>o.modelId==="opencode/big-pickle")?.modelId||e.find(o=>/free$/i.test(o.modelId))?.modelId||e[0]?.modelId||""}function U(e,t){return B(t)&&!/\bfree\b/i.test(e)?`${e} (free)`:e}function B(e){const t=e.cost;if(!t||typeof t!="object"||Array.isArray(t))return!1;const o=t,n=o.cache&&typeof o.cache=="object"&&!Array.isArray(o.cache)?o.cache:{};return[o.input,o.output,n.read,n.write].every(a=>Number(a??0)===0)}function W(e){const t=e.limit&&typeof e.limit=="object"&&!Array.isArray(e.limit)?e.limit:{},o=Number(t.context??0),n=Number(t.output??0);return o>0&&n>0?`Context ${o}, output ${n}`:o>0?`Context ${o}`:"OpenCode model"}function z(){try{const e=process.env.ACA_MIMO_COMMAND||"mimo",t=g(e,["models","--verbose"],{encoding:"utf8",timeout:15e3,maxBuffer:2*1024*1024,stdio:["ignore","pipe","pipe"]}),o=J(t);if(!o.length)return null;const n=[{id:"agent",name:"Agent",description:"Run MimoCode with normal workspace permissions."},{id:"agent-full-access",name:"Agent (full access)",description:"Run MimoCode and auto-approve supported local permissions."}],a=q(o);return{source:"mimo-cli",fetchedAt:Date.now(),contextUsage:!0,contextCompaction:!1,modes:n,models:o.map(i=>({modelId:i.modelId,name:i.displayName,description:i.description,metadata:i.metadata})),configOptions:[{id:"mode",name:"Mode",category:"mode",type:"select",currentValue:"agent-full-access",options:n.map(i=>({value:i.id,name:i.name,description:i.description}))},{id:"model",name:"Model",category:"model",type:"select",currentValue:o.some(i=>i.modelId==="mimo/mimo-auto")?"mimo/mimo-auto":o[0]?.modelId,options:o.map(i=>({value:i.modelId,name:i.displayName,description:i.description}))},{id:"variant",name:"Variant",category:"thought_level",type:"select",currentValue:a.some(i=>i.value==="high")?"high":a[0]?.value,options:a}]}}catch{return null}}function J(e){const t=e.split(/\r?\n/),o=[];let n=0;for(;n<t.length;){const a=t[n]?.trim()??"";if(n+=1,!/^[a-z0-9_.-]+\/[a-z0-9_.-]+$/i.test(a))continue;const i=[];let s=0,c=!1;for(;n<t.length;){const d=t[n]??"";if(n+=1,!(!c&&!d.trim().startsWith("{"))&&(c=!0,i.push(d),s+=f(d,"{")-f(d,"}"),c&&s<=0))break}const r=A(i.join(`
1
+ import{execFileSync as g}from"node:child_process";import m from"node:os";import{readJsonFile as I,writeJsonFile as v}from"./fs.js";import{getRuntimeStatePath as y}from"./paths.js";import{acaServerRequest as w}from"./aca-server-client.js";import{loadAcaConfig as C}from"./aca-config.js";import{providerHealthSnapshot as x}from"./provider-health.js";import{readCodexCapabilities as O}from"./codex-capabilities.js";import{AICA_VERSION as _}from"../version.js";import{applyProjectSync as k}from"./project-sync.js";const b=3e4,E=360*60*1e3,S=360*60*1e3;let p=null,u=null;async function D(e=C(),t={}){if(!e.token)return{ok:!1,skipped:!0,reason:"not_logged_in"};const o=await w("POST","/api/heartbeat",{machineId:e.machineId,machineName:e.machineName,machineInfo:{platform:m.platform(),architecture:m.arch(),osRelease:m.release(),acaVersion:V(),hostname:m.hostname()},workspaceId:e.defaultWorkspaceId,agentConfigs:t.includeProviderDetails===!1?[]:await N(e),projects:e.projects.map(n=>({projectId:n.projectId,workspaceId:n.workspaceId,name:n.name,rootPath:n.rootPath}))});return k(e,o),o}async function N(e){const t=x(),o=await O(),n=o?.capabilities??j();return[{agentId:`${e.machineId}:builtin:codex`,workspaceId:e.defaultWorkspaceId,name:"Codex",agentType:"codex",cliType:"builtin",machineId:e.machineId,model:o?.defaultModel||"gpt-5.5",mode:"agent-full-access",raw:{providerStatus:t.codex,capabilities:n}},{agentId:`${e.machineId}:builtin:mimo`,workspaceId:e.defaultWorkspaceId,name:"MimoCode",agentType:"mimo",cliType:"builtin",machineId:e.machineId,model:"mimo/mimo-auto",mode:"agent-full-access",raw:{providerStatus:t.mimo,capabilities:R()}},{agentId:`${e.machineId}:builtin:opencode`,workspaceId:e.defaultWorkspaceId,name:"OpenCode",agentType:"opencode",cliType:"builtin",machineId:e.machineId,model:process.env.ACA_OPENCODE_DEFAULT_MODEL||null,mode:"agent-full-access",raw:{providerStatus:t.opencode,capabilities:$()}}]}function V(e=process.env){return e.ACA_VERSION?.trim()||_}function j(){const e=[{id:"read-only",name:"Read-only",description:"Requires approval to edit files and run commands."},{id:"agent",name:"Agent",description:"Read and edit files, and run commands."},{id:"agent-full-access",name:"Agent (full access)",description:"Edit files and run commands with full access."}],t=[{modelId:"gpt-5.5",name:"gpt-5.5",description:"Latest frontier Codex model"},{modelId:"gpt-5.4",name:"gpt-5.4",description:"Frontier Codex model"},{modelId:"gpt-5.4-mini",name:"gpt-5.4-mini",description:"Smaller, faster Codex model"}],o=[{value:"low",name:"Low",description:"Fastest responses"},{value:"medium",name:"Medium",description:"Balanced reasoning"},{value:"high",name:"High",description:"More reasoning for difficult tasks"},{value:"xhigh",name:"X High",description:"Extra reasoning for complex tasks"}];return{source:"aca-static",fetchedAt:Date.now(),contextUsage:!0,contextCompaction:!0,modes:e,models:t,configOptions:[{id:"mode",name:"Mode",category:"mode",type:"select",currentValue:"agent-full-access",options:e.map(n=>({value:n.id,name:n.name,description:n.description}))},{id:"model",name:"Model",category:"model",type:"select",currentValue:"gpt-5.5",options:t.map(n=>({value:n.modelId,name:n.name,description:n.description}))},{id:"reasoning_effort",name:"Reasoning effort",category:"thought_level",type:"select",currentValue:"medium",options:o}]}}function H(){const e=[{id:"agent",name:"Agent",description:"Run MimoCode with normal workspace permissions."},{id:"agent-full-access",name:"Agent (full access)",description:"Run MimoCode and auto-approve supported local permissions."}],t=[{modelId:"mimo/mimo-auto",name:"MiMo Auto (free)",description:"MiMo Auto free model"},{modelId:"xiaomi/mimo-v2.5",name:"mimo-v2.5",description:"MimoCode v2.5"},{modelId:"xiaomi/mimo-v2.5-pro",name:"mimo-v2.5-pro",description:"MimoCode v2.5 Pro"},{modelId:"xiaomi/mimo-v2.5-pro-ultraspeed",name:"mimo-v2.5-pro-ultraspeed",description:"MimoCode v2.5 Pro UltraSpeed"}],o=[{value:"minimal",name:"Minimal",description:"Fastest responses"},{value:"high",name:"High",description:"More reasoning for difficult tasks"},{value:"max",name:"Max",description:"Maximum reasoning when supported"}];return{source:"aca-static",fetchedAt:Date.now(),contextUsage:!0,contextCompaction:!1,modes:e,models:t,configOptions:[{id:"mode",name:"Mode",category:"mode",type:"select",currentValue:"agent-full-access",options:e.map(n=>({value:n.id,name:n.name,description:n.description}))},{id:"model",name:"Model",category:"model",type:"select",currentValue:"mimo/mimo-auto",options:t.map(n=>({value:n.modelId,name:n.name,description:n.description}))},{id:"variant",name:"Variant",category:"thought_level",type:"select",currentValue:"high",options:o}]}}function R(){const e=Date.now();if(p&&p.expiresAtMs>e)return p.capabilities;const t=z()??H();return p={expiresAtMs:e+E,capabilities:t},t}function T(){const e=[{id:"plan",name:"Plan",description:"Inspect the project and propose changes."},{id:"build",name:"Build",description:"Read and edit files, and run commands when approved."},{id:"agent-full-access",name:"Agent (full access)",description:"Run OpenCode with ACA full-access mode mapping."}],t=[{modelId:"",name:"Default",description:"Use the model selected by OpenCode configuration."}];return{source:"aca-static",fetchedAt:Date.now(),contextUsage:!0,contextCompaction:!1,modes:e,models:t,configOptions:[{id:"mode",name:"Mode",category:"mode",type:"select",currentValue:"agent-full-access",options:e.map(o=>({value:o.id,name:o.name,description:o.description}))},{id:"model",name:"Model",category:"model",type:"text",currentValue:process.env.ACA_OPENCODE_DEFAULT_MODEL||"",options:t.map(o=>({value:o.modelId,name:o.name,description:o.description}))}]}}function $(){const e=Date.now();if(u&&u.expiresAtMs>e)return u.capabilities;const t=L()??T();return u={expiresAtMs:e+S,capabilities:t},t}function L(){try{const e=process.env.ACA_OPENCODE_COMMAND||"opencode",t=g(e,["models","--verbose"],{windowsHide:!0,encoding:"utf8",timeout:15e3,maxBuffer:8*1024*1024,stdio:["ignore","pipe","pipe"]}),o=P(t);if(!o.length)return null;const n=[{id:"plan",name:"Plan",description:"Inspect the project and propose changes."},{id:"build",name:"Build",description:"Read and edit files, and run commands when approved."},{id:"agent-full-access",name:"Agent (full access)",description:"Run OpenCode with ACA full-access mode mapping."}],a=F(o);return{source:"opencode-cli",fetchedAt:Date.now(),contextUsage:!0,contextCompaction:!1,modes:n,models:o.map(i=>({modelId:i.modelId,name:i.displayName,description:i.description,metadata:i.metadata})),configOptions:[{id:"mode",name:"Mode",category:"mode",type:"select",currentValue:"agent-full-access",options:n.map(i=>({value:i.id,name:i.name,description:i.description}))},{id:"model",name:"Model",category:"model",type:"select",currentValue:a,options:o.map(i=>({value:i.modelId,name:i.displayName,description:i.description}))}]}}catch{return null}}function P(e){const t=e.split(/\r?\n/),o=[];let n=0;for(;n<t.length;){const a=t[n]?.trim()??"";if(n+=1,!/^[a-z0-9_.-]+\/[a-z0-9_.-]+$/i.test(a))continue;const i=[];let s=0,c=!1;for(;n<t.length;){const d=t[n]??"";if(n+=1,!(!c&&!d.trim().startsWith("{"))&&(c=!0,i.push(d),s+=f(d,"{")-f(d,"}"),c&&s<=0))break}const r=A(i.join(`
2
+ `));if(!r)continue;const l=M(r.name,r.id,a)??a;o.push({modelId:a,displayName:U(l,r),description:W(r),metadata:r})}return o}function F(e){const t=process.env.ACA_OPENCODE_DEFAULT_MODEL?.trim();return t&&e.some(o=>o.modelId===t)?t:e.find(o=>o.modelId==="opencode/big-pickle")?.modelId||e.find(o=>/free$/i.test(o.modelId))?.modelId||e[0]?.modelId||""}function U(e,t){return B(t)&&!/\bfree\b/i.test(e)?`${e} (free)`:e}function B(e){const t=e.cost;if(!t||typeof t!="object"||Array.isArray(t))return!1;const o=t,n=o.cache&&typeof o.cache=="object"&&!Array.isArray(o.cache)?o.cache:{};return[o.input,o.output,n.read,n.write].every(a=>Number(a??0)===0)}function W(e){const t=e.limit&&typeof e.limit=="object"&&!Array.isArray(e.limit)?e.limit:{},o=Number(t.context??0),n=Number(t.output??0);return o>0&&n>0?`Context ${o}, output ${n}`:o>0?`Context ${o}`:"OpenCode model"}function z(){try{const e=process.env.ACA_MIMO_COMMAND||"mimo",t=g(e,["models","--verbose"],{windowsHide:!0,encoding:"utf8",timeout:15e3,maxBuffer:2*1024*1024,stdio:["ignore","pipe","pipe"]}),o=J(t);if(!o.length)return null;const n=[{id:"agent",name:"Agent",description:"Run MimoCode with normal workspace permissions."},{id:"agent-full-access",name:"Agent (full access)",description:"Run MimoCode and auto-approve supported local permissions."}],a=q(o);return{source:"mimo-cli",fetchedAt:Date.now(),contextUsage:!0,contextCompaction:!1,modes:n,models:o.map(i=>({modelId:i.modelId,name:i.displayName,description:i.description,metadata:i.metadata})),configOptions:[{id:"mode",name:"Mode",category:"mode",type:"select",currentValue:"agent-full-access",options:n.map(i=>({value:i.id,name:i.name,description:i.description}))},{id:"model",name:"Model",category:"model",type:"select",currentValue:o.some(i=>i.modelId==="mimo/mimo-auto")?"mimo/mimo-auto":o[0]?.modelId,options:o.map(i=>({value:i.modelId,name:i.displayName,description:i.description}))},{id:"variant",name:"Variant",category:"thought_level",type:"select",currentValue:a.some(i=>i.value==="high")?"high":a[0]?.value,options:a}]}}catch{return null}}function J(e){const t=e.split(/\r?\n/),o=[];let n=0;for(;n<t.length;){const a=t[n]?.trim()??"";if(n+=1,!/^[a-z0-9_.-]+\/[a-z0-9_.-]+$/i.test(a))continue;const i=[];let s=0,c=!1;for(;n<t.length;){const d=t[n]??"";if(n+=1,!(!c&&!d.trim().startsWith("{"))&&(c=!0,i.push(d),s+=f(d,"{")-f(d,"}"),c&&s<=0))break}const r=A(i.join(`
3
3
  `));if(!r)continue;const l=M(r.name,r.id,a)??a;o.push({modelId:a,displayName:X(l,r),description:K(r),metadata:r})}return o}function q(e){const t=new Set;for(const a of e){const i=a.metadata.variants;if(!(!i||typeof i!="object"||Array.isArray(i)))for(const s of Object.keys(i))t.add(s)}const o=["minimal","low","medium","high","max"].filter(a=>t.has(a));return(o.length?o:["minimal","high","max"]).map(a=>({value:a,name:Q(a),description:a==="high"?"More reasoning for difficult tasks":a==="max"?"Maximum reasoning when supported":"Fastest responses"}))}function X(e,t){return G(t)&&!/\bfree\b/i.test(e)?`${e} (free)`:e}function G(e){const t=e.cost;if(!t||typeof t!="object"||Array.isArray(t))return!1;const o=t,n=o.cache&&typeof o.cache=="object"&&!Array.isArray(o.cache)?o.cache:{};return[o.input,o.output,n.read,n.write].every(a=>Number(a??0)===0)}function K(e){const t=e.limit&&typeof e.limit=="object"&&!Array.isArray(e.limit)?e.limit:{},o=Number(t.context??0);return o>0?`Context ${o}`:"MimoCode model"}function A(e){try{const t=JSON.parse(e);return t&&typeof t=="object"&&!Array.isArray(t)?t:null}catch{return null}}function M(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim()}function Q(e){return e.slice(0,1).toUpperCase()+e.slice(1)}function f(e,t){let o=0;for(const n of e)n===t&&(o+=1);return o}function ce(e){let t=!1;const o=async(i,s="heartbeat")=>{const c=new Date().toISOString();try{const r=await D(C(),{includeProviderDetails:i});if(r.skipped){h({lastHeartbeatAt:c,lastHeartbeatStatus:"skipped",lastHeartbeatReason:r.reason??"unknown"}),e.debug(`${s} skipped: ${r.reason??"unknown"}`);return}h({lastHeartbeatAt:c,lastHeartbeatStatus:"ok",lastHeartbeatProjectCount:r.projectCount??null,presenceExpiresAtMs:r.presenceExpiresAtMs??null}),e.debug(`${s} ok projects=${r.projectCount??0}`)}catch(r){const l=r instanceof Error?r.message:String(r);h({lastHeartbeatAt:c,lastHeartbeatStatus:"error",lastHeartbeatError:l}),e.warn(`${s} failed: ${l}`)}},n=async()=>{if(!t){t=!0;try{await o(!0)}finally{t=!1}}};return(async()=>{if(!t){t=!0;try{await o(!1,"initial presence heartbeat"),await o(!0)}finally{t=!1}}})(),setInterval(()=>{n()},b)}function h(e){const t=I(y())??{};v(y(),{...t,heartbeatIntervalMs:b,...e})}export{b as HEARTBEAT_INTERVAL_MS,V as reportedAicaVersion,D as sendHeartbeat,ce as startHeartbeatLoop};
@@ -1,5 +1,5 @@
1
- import{managementActivity as T}from"./management/activity.js";import{managedClaim as Z}from"./management/claims.js";import{activeTerminalService as q}from"./terminal/service.js";import{execFileSync as y}from"node:child_process";import{randomUUID as F}from"node:crypto";import l from"node:fs";import I from"node:os";import u from"node:path";import{acaServerDownloadToFile as tt,acaServerRequest as E}from"./aca-server-client.js";import{loadAcaConfig as et,upsertLocalProject as rt}from"./aca-config.js";import{startLongPollWorker as ot}from"./long-poll-worker.js";import{expandWorkerRuntimePath as nt}from"./worker-runtime-paths.js";import{syncCodexProviderRuntimeConfig as it}from"./codex-provider-runtime-config.js";import{defaultAcpRuntimePool as st}from"../acp/client/acp-runtime-pool.js";const L=25e3,at=L+1e4,b=300,ct=3e4;let x=null;function ie(t){return ot({run:async()=>{const e=et();if(!e.token)throw new Error("Worker 尚未配置认证令牌");const r=await Z("machine",()=>E("GET",`/api/client/machine-operations/claim?machineId=${encodeURIComponent(e.machineId)}&waitMs=${L}`,void 0,{timeoutMs:at}));if(!r.item)return;const o=T.track("machine");try{const n=await lt(r.item);await E("POST",`/api/client/machine-operations/${encodeURIComponent(r.item.requestId)}/complete`,{result:n})}catch(n){const s=n instanceof Error?n.message:String(n);t.warn(`machine filesystem request failed request=${r.item.requestId}: ${s}`),await E("POST",`/api/client/machine-operations/${encodeURIComponent(r.item.requestId)}/fail`,{message:s}).catch(()=>{T.uncertain.add("machine-finalize")})}finally{o()}},onError:(e,r)=>t.warn(`machine filesystem worker failed, retry in ${r}ms: ${e instanceof Error?e.message:String(e)}`)})}async function lt(t){if(t.operation==="sync_codex_provider_config"){const e=await it(),r=await st.retireProviderRuntimes("codex-acp");return{configured:!!e,revision:e?.revision??null,retiredRuntimes:r}}if(t.operation==="filesystem_roots")return Nt();if(t.operation==="list_directory")return $t({directoryPath:String(t.payload.path||""),includeHidden:t.payload.includeHidden===!0});if(t.operation==="register_project")return Ot(t.payload);if(t.operation==="list_project_directory")return dt(t.payload);if(t.operation==="upload_project_file")return pt(t.payload);if(t.operation==="mutate_project_files")return ht(t.payload);if(t.operation==="get_project_git_status")return H(t.payload);if(t.operation==="get_project_git_diff")return Pt(t.payload);if(t.operation==="get_project_git_log")return Et(t.payload);if(t.operation==="get_project_git_commit")return bt(t.payload);if(t.operation==="get_worktree_status")return k(t.payload);if(t.operation==="commit_worktree")return ut(t.payload);if(t.operation==="cleanup_worktree")return ft(t.payload);throw new Error("不支持的 Machine 文件系统操作。 ")}function k(t){const e=N(String(t.worktreePath||""));if(!l.existsSync(e))return{exists:!1,isRepository:!1,dirty:!1,changedFiles:0,ahead:0};const r=p(e);if(!w(r))return{exists:!0,isRepository:!1,dirty:At(r),changedFiles:null,ahead:0};const o=H({rootPath:r}),n=String(t.baseCommit||"").trim(),s=n&&/^[0-9a-f]{7,64}$/i.test(n)?vt(r,n):0;return{exists:!0,isRepository:!0,dirty:Array.isArray(o.files)&&o.files.length>0,changedFiles:Array.isArray(o.files)?o.files.length:0,branch:o.branch,ahead:s,files:Array.isArray(o.files)?o.files.slice(0,50):[],truncated:o.truncated===!0}}function ut(t){const e=p(String(t.worktreePath||"")),r=String(t.message||"").trim();if(!r)throw new Error("提交说明不能为空。");if(!w(e))throw new Error("当前 Worktree 不是 Git 仓库,无法提交。");y("git",["-C",e,"add","-A"],{stdio:"pipe",timeout:3e4});try{return y("git",["-C",e,"diff","--cached","--quiet"],{stdio:"pipe",timeout:1e4}),{committed:!1,reason:"no_changes",...k(t)}}catch(o){if(Number(o.status)!==1)throw o}return y("git",["-C",e,"commit","-m",r],{stdio:"pipe",timeout:6e4}),{committed:!0,commit:m(e,["rev-parse","HEAD"],8*1024).trim(),...k(t)}}function ft(t){const e=N(String(t.worktreePath||"")),r=p(String(t.projectRoot||""));if(h(e)===h(r))throw new Error("不能清理项目主目录。");if(!l.existsSync(e))return{removed:!1,reason:"not_found"};const o=p(e);if(q?.hasRunningInDirectory(o,String(t.sessionId||"")))throw new Error("请先结束此目录中的会话终端,再清理 Worktree。");const n=String(t.branchName||"").trim(),s=w(o)&&w(r);if(s){if(y("git",["-C",r,"worktree","remove","--force",o],{stdio:"pipe",timeout:6e4}),t.deleteBranch===!0&&n)try{y("git",["-C",r,"branch","-D",n],{stdio:"pipe",timeout:3e4})}catch(i){const a=String(i.stderr||i);if(!/not found|not exist/i.test(a))throw i}}else l.rmSync(o,{recursive:!0,force:!0,maxRetries:2,retryDelay:200});return{removed:!0,branchDeleted:!!(s&&t.deleteBranch===!0&&n)}}function dt(t){const e=p(String(t.rootPath||"")),r=S(String(t.relativePath||"")),o=v(e,r,!0),n=Math.max(0,Number(t.offset||0)),s=Math.min(300,Math.max(20,Number(t.limit||200))),i=t.sort==="modified-desc"||t.sort==="modified-asc"?t.sort:"name",a=l.readdirSync(o,{withFileTypes:!0}).filter(c=>!c.isSymbolicLink()).map(c=>({name:c.name,path:V(e,u.join(o,c.name)),type:c.isDirectory()?"directory":c.isFile()?"file":"other",hidden:c.name.startsWith("."),extension:c.isFile()?u.extname(c.name).slice(1).toLowerCase():"",modifiedAt:i==="name"?void 0:mt(u.join(o,c.name))})).filter(c=>c.type!=="other").sort((c,d)=>{if(c.type!==d.type)return c.type==="directory"?-1:1;if(i!=="name"){if(c.modifiedAt==null&&d.modifiedAt!=null)return 1;if(d.modifiedAt==null&&c.modifiedAt!=null)return-1;const P=(c.modifiedAt??0)-(d.modifiedAt??0);if(P)return i==="modified-desc"?-P:P}return c.name.localeCompare(d.name,void 0,{numeric:!0,sensitivity:"base"})}),f=a.slice(n,n+s);return{path:r,rootKind:t.rootKind==="worktree"?"worktree":"project",items:f,total:a.length,nextOffset:n+f.length<a.length?n+f.length:null}}function mt(t){try{const e=l.lstatSync(t);return e.isSymbolicLink()?null:e.mtimeMs}catch{return null}}async function pt(t){const e=String(t.uploadId||"").trim();if(!e)throw new Error("项目上传任务缺少 uploadId。");const r=p(String(t.rootPath||"")),o=S(String(t.relativeDirectory||"")),n=v(r,o,!0),s=M(String(t.fileName||"")),i=Number(t.sizeBytes),a=String(t.sha256||"").trim().toLowerCase();if(!Number.isSafeInteger(i)||i<0)throw new Error("项目上传文件大小无效。");if(!/^[0-9a-f]{64}$/.test(a))throw new Error("项目上传文件摘要无效。");const f=u.join(n,`.aca-upload-${F()}.tmp`);try{const c=await tt(`/api/client/project-uploads/${encodeURIComponent(e)}`,f,{maxBytes:i,timeoutMs:3e5});if(c.sizeBytes!==i)throw new Error("项目上传文件大小校验失败。");if(c.sha256.toLowerCase()!==a)throw new Error("项目上传文件完整性校验失败。");const d=gt(r,o,s,f);return{name:u.basename(d),path:V(r,d),directory:o,size:c.sizeBytes,sha256:c.sha256,renamed:u.basename(d)!==s,rootKind:t.rootKind==="worktree"?"worktree":"project"}}finally{l.rmSync(f,{force:!0})}}function ht(t){const e=p(String(t.rootPath||"")),r=t.action&&typeof t.action=="object"?t.action:{};if(r.type==="delete")return wt(e,String(r.path||""),r.recursive===!0,t.rootKind);throw new Error("project_file_operation_unsupported")}function wt(t,e,r,o){const n=S(e);if(!n)throw new Error("project_file_root_protected");yt(n);const s=n.split("/"),i=s.slice(0,-1).join("/"),a=v(t,i,!0),f=u.join(a,s.at(-1)||"");let c;try{c=l.lstatSync(f)}catch(d){throw d.code==="ENOENT"?new Error("project_file_not_found"):d}if(c.isSymbolicLink())throw new Error("project_file_symbolic_link");if(!c.isFile()&&!c.isDirectory())throw new Error("project_file_type_unsupported");if(c.isDirectory()&&!r&&l.readdirSync(f).length>0)throw new Error("project_directory_not_empty");return c.isDirectory()&&r?l.rmSync(f,{recursive:!0,force:!1,maxRetries:2,retryDelay:150}):c.isDirectory()?l.rmdirSync(f):l.unlinkSync(f),{operation:"delete",path:n,entryType:c.isDirectory()?"directory":"file",parentPath:i,affectedDirectories:[i],rootKind:o==="worktree"?"worktree":"project"}}function yt(t){const e=t.split("/")[0].toLocaleLowerCase("en-US");if([".git",".aca",".aica"].includes(e))throw new Error("project_file_protected")}function gt(t,e,r,o){const n=p(t),s=S(e),i=v(n,s,!0),a=M(r);if(l.realpathSync.native(u.dirname(o))!==i)throw new Error("项目上传临时文件不在目标目录中。");const c=l.lstatSync(o);if(!c.isFile()||c.isSymbolicLink())throw new Error("项目上传临时文件无效。");for(let d=1;d<=1e4;d+=1){const P=d===1?a:St(a,d),_=u.join(i,P);try{return l.linkSync(o,_),l.chmodSync(_,420),l.rmSync(o,{force:!0}),_}catch(A){if(O(A))continue;if(!_t(A))throw A;try{return l.copyFileSync(o,_,l.constants.COPYFILE_EXCL),l.chmodSync(_,420),l.rmSync(o,{force:!0}),_}catch($){if(O($))continue;throw $}}}throw new Error("同名文件过多,无法生成可用文件名。")}function M(t){const e=t.trim();if(!e||e==="."||e===".."||/[\\/\x00-\x1F]/.test(e))throw new Error("项目上传文件名无效。");if(process.platform==="win32"&&(/[<>:"|?*]/.test(e)||/[. ]$/.test(e)))throw new Error("项目上传文件名在 Windows 上无效。");return e.slice(0,180)}function St(t,e){const r=u.extname(t);return`${r?t.slice(0,-r.length):t} (${e})${r}`}function O(t){return!!(t&&typeof t=="object"&&t.code==="EEXIST")}function _t(t){const e=t&&typeof t=="object"?t.code:"";return["EPERM","EACCES","EXDEV","ENOTSUP","EOPNOTSUPP"].includes(String(e||""))}const G=500,j=2*1024*1024,g=2*1024*1024;function H(t){const e=p(String(t.rootPath||""));if(!w(e))return{isRepository:!1,branch:null,files:[],ahead:0,behind:0};const o=m(e,["status","--porcelain=v1","-z","--untracked-files=all","--no-renames"],j).split("\0").filter(Boolean).slice(0,G),n=o.map(a=>jt(a)).filter(a=>!!a),s=D(m(e,["diff","--no-ext-diff","--numstat","-z","--no-renames","HEAD","--","."],j));for(const a of n){const f=s.get(a.path);if(f)a.additions=f.additions,a.deletions=f.deletions;else if(a.status==="untracked"){const c=W(e,a.path);a.additions=c.additions,a.deletions=c.deletions}}const i=Ct(e);return{isRepository:!0,branch:Rt(e),files:n,ahead:i.ahead,behind:i.behind,truncated:o.length>=G}}function Pt(t){const e=p(String(t.rootPath||"")),r=S(String(t.relativePath||""));if(!r)throw new Error("Diff 文件路径不能为空。");if(!w(e))return{isRepository:!1,path:r,diff:"",additions:0,deletions:0};const o=U(e,r),n=kt(e,r),s=n?m(e,["diff","--no-ext-diff","--unified=80","HEAD","--",r],g):z(e,["diff","--no-ext-diff","--no-index","--unified=80",process.platform==="win32"?"NUL":"/dev/null",o],g),i=n?D(m(e,["diff","--no-ext-diff","--numstat","-z","--no-renames","HEAD","--",r],32*1024)).get(r):W(e,r);return{isRepository:!0,path:r,diff:K(s),additions:i?.additions??0,deletions:i?.deletions??0,truncated:s.length>g}}function Et(t){const e=p(String(t.rootPath||""));if(!w(e))return{isRepository:!1,items:[]};if(!Dt(e))return{isRepository:!0,items:[]};const r=Math.min(200,Math.max(20,Number(t.limit||100)));return{isRepository:!0,items:m(e,["log",`--max-count=${r}`,"--date=iso-strict","--pretty=format:%H%x1f%h%x1f%an%x1f%ae%x1f%aI%x1f%D%x1f%s%x1f%b%x1e"],j).split("").map(i=>xt(i)).filter(i=>!!i),limit:r}}function bt(t){const e=p(String(t.rootPath||"")),r=String(t.commit||"").trim();if(!/^[0-9a-f]{7,64}$/i.test(r))throw new Error("Git 提交标识无效。");if(!w(e))return{isRepository:!1,commit:r,diff:"",additions:0,deletions:0};m(e,["cat-file","-e",`${r}^{commit}`],8*1024);const o=m(e,["show","--no-ext-diff","--no-color","--format=","--stat","--patch","--unified=40",r],g),n=[...D(m(e,["show","--no-ext-diff","--numstat","-z","--no-renames","--format=",r],j)).values()];return{isRepository:!0,commit:r,diff:K(o),additions:n.reduce((s,i)=>s+(i.additions||0),0),deletions:n.reduce((s,i)=>s+(i.deletions||0),0),changedFiles:n.length,truncated:o.length>g}}function xt(t){const e=t.replace(/^\s+|\s+$/g,"");if(!e)return null;const r=e.split(""),o=String(r[0]||"").trim();return o?{hash:o,shortHash:String(r[1]||o.slice(0,8)).trim(),authorName:String(r[2]||"").trim(),authorEmail:String(r[3]||"").trim(),authoredAt:String(r[4]||"").trim(),refs:String(r[5]||"").trim(),subject:String(r[6]||"").trim(),body:r.slice(7).join("").trim()}:null}function jt(t){if(t.length<4)return null;const e=t[0]||" ",r=t[1]||" ",o=S(t.slice(3));return o?{path:o,status:e==="?"&&r==="?"?"untracked":e==="U"||r==="U"?"conflicted":e==="D"||r==="D"?"deleted":e==="A"||r==="A"?"added":e==="R"||r==="R"?"renamed":"modified",indexStatus:e,worktreeStatus:r,staged:e!==" "&&e!=="?",additions:null,deletions:null}:null}function D(t){const e=new Map;for(const r of t.split("\0")){if(!r)continue;const o=B(r);if(!o||!o.path)continue;const n=S(o.path);n&&e.set(n,{additions:o.additions,deletions:o.deletions})}return e}function W(t,e){const r=U(t,e),n=z(t,["diff","--no-ext-diff","--no-index","--numstat","-z","--",process.platform==="win32"?"NUL":"/dev/null",r],32*1024).split("\0",1)[0]||"",s=B(n);return s?{additions:s.additions,deletions:s.deletions}:{additions:null,deletions:null}}function B(t){const e=t.indexOf(" "),r=e<0?-1:t.indexOf(" ",e+1);if(e<0||r<0)return null;const o=t.slice(0,e),n=t.slice(e+1,r);return{additions:/^\d+$/.test(o)?Number(o):null,deletions:/^\d+$/.test(n)?Number(n):null,path:t.slice(r+1)}}function w(t){try{return m(t,["rev-parse","--is-inside-work-tree"],8*1024).trim()==="true"}catch(e){if(String(e.code||"")==="ENOENT")throw new Error("设备未安装 Git。");return!1}}function vt(t,e){try{const r=m(t,["rev-list","--count",`${e}..HEAD`],8192).trim(),o=Number(r);return Number.isSafeInteger(o)&&o>0?o:0}catch{return 0}}function At(t){try{return l.readdirSync(t).length>0}catch{return!1}}function kt(t,e){try{return m(t,["ls-files","--error-unmatch","--",e],8*1024),!0}catch{return!1}}function Dt(t){try{return m(t,["rev-parse","--verify","HEAD"],8*1024),!0}catch{return!1}}function Rt(t){try{return m(t,["symbolic-ref","--quiet","--short","HEAD"],8*1024).trim()||null}catch{try{return`HEAD (${m(t,["rev-parse","--short","HEAD"],8*1024).trim()})`}catch{return null}}}function Ct(t){try{const e=m(t,["rev-list","--left-right","--count","HEAD...@{upstream}"],8192).trim().split(/\s+/).map(Number);return{ahead:Number.isFinite(e[0])?e[0]:0,behind:Number.isFinite(e[1])?e[1]:0}}catch{return{ahead:0,behind:0}}}function U(t,e){const r=u.resolve(t,...e.split("/")),o=u.relative(t,r);if(o.startsWith("..")||u.isAbsolute(o))throw new Error("Diff 路径超出项目范围。");return r}function m(t,e,r){return y("git",["-C",t,...e],{encoding:"utf8",timeout:2e4,maxBuffer:r,stdio:["ignore","pipe","pipe"]})}function z(t,e,r){try{return m(t,e,r)}catch(o){const n=String(o.stdout||"");if(n)return n;if(Number(o.status)===1)return"";throw o}}function K(t){return t.length<=g?t:`${t.slice(0,g)}
1
+ import{executeExternalCodexOperation as Z}from"./external-codex-worker.js";import{managementActivity as T}from"./management/activity.js";import{managedClaim as q}from"./management/claims.js";import{activeTerminalService as tt}from"./terminal/service.js";import{execFileSync as y}from"node:child_process";import{randomUUID as F}from"node:crypto";import l from"node:fs";import I from"node:os";import u from"node:path";import{acaServerDownloadToFile as et,acaServerRequest as E}from"./aca-server-client.js";import{loadAcaConfig as rt,upsertLocalProject as ot}from"./aca-config.js";import{startLongPollWorker as nt}from"./long-poll-worker.js";import{expandWorkerRuntimePath as it}from"./worker-runtime-paths.js";import{syncCodexProviderRuntimeConfig as st}from"./codex-provider-runtime-config.js";import{defaultAcpRuntimePool as at}from"../acp/client/acp-runtime-pool.js";const L=25e3,ct=L+1e4,x=300,lt=3e4;let b=null;function ae(t){return nt({run:async()=>{const e=rt();if(!e.token)throw new Error("Worker 尚未配置认证令牌");const r=await q("machine",()=>E("GET",`/api/client/machine-operations/claim?machineId=${encodeURIComponent(e.machineId)}&waitMs=${L}`,void 0,{timeoutMs:ct}));if(!r.item)return;const o=T.track("machine");try{const n=await ut(r.item);await E("POST",`/api/client/machine-operations/${encodeURIComponent(r.item.requestId)}/complete`,{result:n})}catch(n){const s=n instanceof Error?n.message:String(n);t.warn(`machine filesystem request failed request=${r.item.requestId}: ${s}`),await E("POST",`/api/client/machine-operations/${encodeURIComponent(r.item.requestId)}/fail`,{message:s}).catch(()=>{T.uncertain.add("machine-finalize")})}finally{o()}},onError:(e,r)=>t.warn(`machine filesystem worker failed, retry in ${r}ms: ${e instanceof Error?e.message:String(e)}`)})}async function ut(t){if(t.operation.startsWith("external_codex_"))return Z(t.operation,t.payload);if(t.operation==="sync_codex_provider_config"){const e=await st(),r=await at.retireProviderRuntimes("codex-acp");return{configured:!!e,revision:e?.revision??null,retiredRuntimes:r}}if(t.operation==="filesystem_roots")return $t();if(t.operation==="list_directory")return Tt({directoryPath:String(t.payload.path||""),includeHidden:t.payload.includeHidden===!0});if(t.operation==="register_project")return Ht(t.payload);if(t.operation==="list_project_directory")return mt(t.payload);if(t.operation==="upload_project_file")return ht(t.payload);if(t.operation==="mutate_project_files")return wt(t.payload);if(t.operation==="get_project_git_status")return G(t.payload);if(t.operation==="get_project_git_diff")return Et(t.payload);if(t.operation==="get_project_git_log")return xt(t.payload);if(t.operation==="get_project_git_commit")return bt(t.payload);if(t.operation==="get_worktree_status")return k(t.payload);if(t.operation==="commit_worktree")return dt(t.payload);if(t.operation==="cleanup_worktree")return ft(t.payload);throw new Error("不支持的 Machine 文件系统操作。 ")}function k(t){const e=N(String(t.worktreePath||""));if(!l.existsSync(e))return{exists:!1,isRepository:!1,dirty:!1,changedFiles:0,ahead:0};const r=p(e);if(!w(r))return{exists:!0,isRepository:!1,dirty:kt(r),changedFiles:null,ahead:0};const o=G({rootPath:r}),n=String(t.baseCommit||"").trim(),s=n&&/^[0-9a-f]{7,64}$/i.test(n)?At(r,n):0;return{exists:!0,isRepository:!0,dirty:Array.isArray(o.files)&&o.files.length>0,changedFiles:Array.isArray(o.files)?o.files.length:0,branch:o.branch,ahead:s,files:Array.isArray(o.files)?o.files.slice(0,50):[],truncated:o.truncated===!0}}function dt(t){const e=p(String(t.worktreePath||"")),r=String(t.message||"").trim();if(!r)throw new Error("提交说明不能为空。");if(!w(e))throw new Error("当前 Worktree 不是 Git 仓库,无法提交。");y("git",["-C",e,"add","-A"],{windowsHide:!0,stdio:"pipe",timeout:3e4});try{return y("git",["-C",e,"diff","--cached","--quiet"],{windowsHide:!0,stdio:"pipe",timeout:1e4}),{committed:!1,reason:"no_changes",...k(t)}}catch(o){if(Number(o.status)!==1)throw o}return y("git",["-C",e,"commit","-m",r],{windowsHide:!0,stdio:"pipe",timeout:6e4}),{committed:!0,commit:m(e,["rev-parse","HEAD"],8*1024).trim(),...k(t)}}function ft(t){const e=N(String(t.worktreePath||"")),r=p(String(t.projectRoot||""));if(h(e)===h(r))throw new Error("不能清理项目主目录。");if(!l.existsSync(e))return{removed:!1,reason:"not_found"};const o=p(e);if(tt?.hasRunningInDirectory(o,String(t.sessionId||"")))throw new Error("请先结束此目录中的会话终端,再清理 Worktree。");const n=String(t.branchName||"").trim(),s=w(o)&&w(r);if(s){if(y("git",["-C",r,"worktree","remove","--force",o],{windowsHide:!0,stdio:"pipe",timeout:6e4}),t.deleteBranch===!0&&n)try{y("git",["-C",r,"branch","-D",n],{windowsHide:!0,stdio:"pipe",timeout:3e4})}catch(i){const a=String(i.stderr||i);if(!/not found|not exist/i.test(a))throw i}}else l.rmSync(o,{recursive:!0,force:!0,maxRetries:2,retryDelay:200});return{removed:!0,branchDeleted:!!(s&&t.deleteBranch===!0&&n)}}function mt(t){const e=p(String(t.rootPath||"")),r=S(String(t.relativePath||"")),o=v(e,r,!0),n=Math.max(0,Number(t.offset||0)),s=Math.min(300,Math.max(20,Number(t.limit||200))),i=t.sort==="modified-desc"||t.sort==="modified-asc"?t.sort:"name",a=l.readdirSync(o,{withFileTypes:!0}).filter(c=>!c.isSymbolicLink()).map(c=>({name:c.name,path:V(e,u.join(o,c.name)),type:c.isDirectory()?"directory":c.isFile()?"file":"other",hidden:c.name.startsWith("."),extension:c.isFile()?u.extname(c.name).slice(1).toLowerCase():"",modifiedAt:i==="name"?void 0:pt(u.join(o,c.name))})).filter(c=>c.type!=="other").sort((c,f)=>{if(c.type!==f.type)return c.type==="directory"?-1:1;if(i!=="name"){if(c.modifiedAt==null&&f.modifiedAt!=null)return 1;if(f.modifiedAt==null&&c.modifiedAt!=null)return-1;const P=(c.modifiedAt??0)-(f.modifiedAt??0);if(P)return i==="modified-desc"?-P:P}return c.name.localeCompare(f.name,void 0,{numeric:!0,sensitivity:"base"})}),d=a.slice(n,n+s);return{path:r,rootKind:t.rootKind==="worktree"?"worktree":"project",items:d,total:a.length,nextOffset:n+d.length<a.length?n+d.length:null}}function pt(t){try{const e=l.lstatSync(t);return e.isSymbolicLink()?null:e.mtimeMs}catch{return null}}async function ht(t){const e=String(t.uploadId||"").trim();if(!e)throw new Error("项目上传任务缺少 uploadId。");const r=p(String(t.rootPath||"")),o=S(String(t.relativeDirectory||"")),n=v(r,o,!0),s=M(String(t.fileName||"")),i=Number(t.sizeBytes),a=String(t.sha256||"").trim().toLowerCase();if(!Number.isSafeInteger(i)||i<0)throw new Error("项目上传文件大小无效。");if(!/^[0-9a-f]{64}$/.test(a))throw new Error("项目上传文件摘要无效。");const d=u.join(n,`.aca-upload-${F()}.tmp`);try{const c=await et(`/api/client/project-uploads/${encodeURIComponent(e)}`,d,{maxBytes:i,timeoutMs:3e5});if(c.sizeBytes!==i)throw new Error("项目上传文件大小校验失败。");if(c.sha256.toLowerCase()!==a)throw new Error("项目上传文件完整性校验失败。");const f=St(r,o,s,d);return{name:u.basename(f),path:V(r,f),directory:o,size:c.sizeBytes,sha256:c.sha256,renamed:u.basename(f)!==s,rootKind:t.rootKind==="worktree"?"worktree":"project"}}finally{l.rmSync(d,{force:!0})}}function wt(t){const e=p(String(t.rootPath||"")),r=t.action&&typeof t.action=="object"?t.action:{};if(r.type==="delete")return yt(e,String(r.path||""),r.recursive===!0,t.rootKind);throw new Error("project_file_operation_unsupported")}function yt(t,e,r,o){const n=S(e);if(!n)throw new Error("project_file_root_protected");gt(n);const s=n.split("/"),i=s.slice(0,-1).join("/"),a=v(t,i,!0),d=u.join(a,s.at(-1)||"");let c;try{c=l.lstatSync(d)}catch(f){throw f.code==="ENOENT"?new Error("project_file_not_found"):f}if(c.isSymbolicLink())throw new Error("project_file_symbolic_link");if(!c.isFile()&&!c.isDirectory())throw new Error("project_file_type_unsupported");if(c.isDirectory()&&!r&&l.readdirSync(d).length>0)throw new Error("project_directory_not_empty");return c.isDirectory()&&r?l.rmSync(d,{recursive:!0,force:!1,maxRetries:2,retryDelay:150}):c.isDirectory()?l.rmdirSync(d):l.unlinkSync(d),{operation:"delete",path:n,entryType:c.isDirectory()?"directory":"file",parentPath:i,affectedDirectories:[i],rootKind:o==="worktree"?"worktree":"project"}}function gt(t){const e=t.split("/")[0].toLocaleLowerCase("en-US");if([".git",".aca",".aica"].includes(e))throw new Error("project_file_protected")}function St(t,e,r,o){const n=p(t),s=S(e),i=v(n,s,!0),a=M(r);if(l.realpathSync.native(u.dirname(o))!==i)throw new Error("项目上传临时文件不在目标目录中。");const c=l.lstatSync(o);if(!c.isFile()||c.isSymbolicLink())throw new Error("项目上传临时文件无效。");for(let f=1;f<=1e4;f+=1){const P=f===1?a:_t(a,f),_=u.join(i,P);try{return l.linkSync(o,_),l.chmodSync(_,420),l.rmSync(o,{force:!0}),_}catch(A){if(O(A))continue;if(!Pt(A))throw A;try{return l.copyFileSync(o,_,l.constants.COPYFILE_EXCL),l.chmodSync(_,420),l.rmSync(o,{force:!0}),_}catch($){if(O($))continue;throw $}}}throw new Error("同名文件过多,无法生成可用文件名。")}function M(t){const e=t.trim();if(!e||e==="."||e===".."||/[\\/\x00-\x1F]/.test(e))throw new Error("项目上传文件名无效。");if(process.platform==="win32"&&(/[<>:"|?*]/.test(e)||/[. ]$/.test(e)))throw new Error("项目上传文件名在 Windows 上无效。");return e.slice(0,180)}function _t(t,e){const r=u.extname(t);return`${r?t.slice(0,-r.length):t} (${e})${r}`}function O(t){return!!(t&&typeof t=="object"&&t.code==="EEXIST")}function Pt(t){const e=t&&typeof t=="object"?t.code:"";return["EPERM","EACCES","EXDEV","ENOTSUP","EOPNOTSUPP"].includes(String(e||""))}const H=500,j=2*1024*1024,g=2*1024*1024;function G(t){const e=p(String(t.rootPath||""));if(!w(e))return{isRepository:!1,branch:null,files:[],ahead:0,behind:0};const o=m(e,["status","--porcelain=v1","-z","--untracked-files=all","--no-renames"],j).split("\0").filter(Boolean).slice(0,H),n=o.map(a=>vt(a)).filter(a=>!!a),s=D(m(e,["diff","--no-ext-diff","--numstat","-z","--no-renames","HEAD","--","."],j));for(const a of n){const d=s.get(a.path);if(d)a.additions=d.additions,a.deletions=d.deletions;else if(a.status==="untracked"){const c=W(e,a.path);a.additions=c.additions,a.deletions=c.deletions}}const i=Nt(e);return{isRepository:!0,branch:Rt(e),files:n,ahead:i.ahead,behind:i.behind,truncated:o.length>=H}}function Et(t){const e=p(String(t.rootPath||"")),r=S(String(t.relativePath||""));if(!r)throw new Error("Diff 文件路径不能为空。");if(!w(e))return{isRepository:!1,path:r,diff:"",additions:0,deletions:0};const o=U(e,r),n=Dt(e,r),s=n?m(e,["diff","--no-ext-diff","--unified=80","HEAD","--",r],g):z(e,["diff","--no-ext-diff","--no-index","--unified=80",process.platform==="win32"?"NUL":"/dev/null",o],g),i=n?D(m(e,["diff","--no-ext-diff","--numstat","-z","--no-renames","HEAD","--",r],32*1024)).get(r):W(e,r);return{isRepository:!0,path:r,diff:K(s),additions:i?.additions??0,deletions:i?.deletions??0,truncated:s.length>g}}function xt(t){const e=p(String(t.rootPath||""));if(!w(e))return{isRepository:!1,items:[]};if(!Ct(e))return{isRepository:!0,items:[]};const r=Math.min(200,Math.max(20,Number(t.limit||100)));return{isRepository:!0,items:m(e,["log",`--max-count=${r}`,"--date=iso-strict","--pretty=format:%H%x1f%h%x1f%an%x1f%ae%x1f%aI%x1f%D%x1f%s%x1f%b%x1e"],j).split("").map(i=>jt(i)).filter(i=>!!i),limit:r}}function bt(t){const e=p(String(t.rootPath||"")),r=String(t.commit||"").trim();if(!/^[0-9a-f]{7,64}$/i.test(r))throw new Error("Git 提交标识无效。");if(!w(e))return{isRepository:!1,commit:r,diff:"",additions:0,deletions:0};m(e,["cat-file","-e",`${r}^{commit}`],8*1024);const o=m(e,["show","--no-ext-diff","--no-color","--format=","--stat","--patch","--unified=40",r],g),n=[...D(m(e,["show","--no-ext-diff","--numstat","-z","--no-renames","--format=",r],j)).values()];return{isRepository:!0,commit:r,diff:K(o),additions:n.reduce((s,i)=>s+(i.additions||0),0),deletions:n.reduce((s,i)=>s+(i.deletions||0),0),changedFiles:n.length,truncated:o.length>g}}function jt(t){const e=t.replace(/^\s+|\s+$/g,"");if(!e)return null;const r=e.split(""),o=String(r[0]||"").trim();return o?{hash:o,shortHash:String(r[1]||o.slice(0,8)).trim(),authorName:String(r[2]||"").trim(),authorEmail:String(r[3]||"").trim(),authoredAt:String(r[4]||"").trim(),refs:String(r[5]||"").trim(),subject:String(r[6]||"").trim(),body:r.slice(7).join("").trim()}:null}function vt(t){if(t.length<4)return null;const e=t[0]||" ",r=t[1]||" ",o=S(t.slice(3));return o?{path:o,status:e==="?"&&r==="?"?"untracked":e==="U"||r==="U"?"conflicted":e==="D"||r==="D"?"deleted":e==="A"||r==="A"?"added":e==="R"||r==="R"?"renamed":"modified",indexStatus:e,worktreeStatus:r,staged:e!==" "&&e!=="?",additions:null,deletions:null}:null}function D(t){const e=new Map;for(const r of t.split("\0")){if(!r)continue;const o=B(r);if(!o||!o.path)continue;const n=S(o.path);n&&e.set(n,{additions:o.additions,deletions:o.deletions})}return e}function W(t,e){const r=U(t,e),n=z(t,["diff","--no-ext-diff","--no-index","--numstat","-z","--",process.platform==="win32"?"NUL":"/dev/null",r],32*1024).split("\0",1)[0]||"",s=B(n);return s?{additions:s.additions,deletions:s.deletions}:{additions:null,deletions:null}}function B(t){const e=t.indexOf(" "),r=e<0?-1:t.indexOf(" ",e+1);if(e<0||r<0)return null;const o=t.slice(0,e),n=t.slice(e+1,r);return{additions:/^\d+$/.test(o)?Number(o):null,deletions:/^\d+$/.test(n)?Number(n):null,path:t.slice(r+1)}}function w(t){try{return m(t,["rev-parse","--is-inside-work-tree"],8*1024).trim()==="true"}catch(e){if(String(e.code||"")==="ENOENT")throw new Error("设备未安装 Git。");return!1}}function At(t,e){try{const r=m(t,["rev-list","--count",`${e}..HEAD`],8192).trim(),o=Number(r);return Number.isSafeInteger(o)&&o>0?o:0}catch{return 0}}function kt(t){try{return l.readdirSync(t).length>0}catch{return!1}}function Dt(t,e){try{return m(t,["ls-files","--error-unmatch","--",e],8*1024),!0}catch{return!1}}function Ct(t){try{return m(t,["rev-parse","--verify","HEAD"],8*1024),!0}catch{return!1}}function Rt(t){try{return m(t,["symbolic-ref","--quiet","--short","HEAD"],8*1024).trim()||null}catch{try{return`HEAD (${m(t,["rev-parse","--short","HEAD"],8*1024).trim()})`}catch{return null}}}function Nt(t){try{const e=m(t,["rev-list","--left-right","--count","HEAD...@{upstream}"],8192).trim().split(/\s+/).map(Number);return{ahead:Number.isFinite(e[0])?e[0]:0,behind:Number.isFinite(e[1])?e[1]:0}}catch{return{ahead:0,behind:0}}}function U(t,e){const r=u.resolve(t,...e.split("/")),o=u.relative(t,r);if(o.startsWith("..")||u.isAbsolute(o))throw new Error("Diff 路径超出项目范围。");return r}function m(t,e,r){return y("git",["-C",t,...e],{windowsHide:!0,encoding:"utf8",timeout:2e4,maxBuffer:r,stdio:["ignore","pipe","pipe"]})}function z(t,e,r){try{return m(t,e,r)}catch(o){const n=String(o.stdout||"");if(n)return n;if(Number(o.status)===1)return"";throw o}}function K(t){return t.length<=g?t:`${t.slice(0,g)}
2
2
 
3
- [Diff 内容过大,已截断]`}function Nt(){const t=process.platform,e=R(t);return{platform:t,roots:e}}function $t(t){if(!t.directoryPath.trim())throw new Error("目录路径不能为空。");return process.platform==="win32"?Lt(t.directoryPath,!!t.includeHidden):It(t.directoryPath,!!t.includeHidden)}function h(t,e=process.platform){const r=e==="win32"?u.win32:u.posix,o=r.normalize(t),n=r.parse(o).root,s=o.length>n.length?o.replace(/[\\/]+$/,""):o;return e==="win32"?s.toLocaleLowerCase("en-US"):s}function Tt(){const t=l.realpathSync(I.homedir()),e=[{id:"home",label:"用户目录",path:t,kind:"home",available:!0}];return t!==u.parse(t).root&&e.push({id:"root",label:"文件系统",path:"/",kind:"root",available:!0}),e}function R(t){if(x?.platform===t&&x.expiresAtMs>Date.now())return x.roots;const e=t==="win32"?Ft():Tt();return x={platform:t,roots:e,expiresAtMs:Date.now()+ct},e}function Ft(){const t=l.realpathSync.native(I.homedir()),e=new Map;e.set(h(t,"win32"),{id:"home",label:"用户目录",path:t,kind:"home",available:!0});try{const r=["$items = Get-CimInstance Win32_LogicalDisk | ForEach-Object {"," [PSCustomObject]@{ Name = $_.DeviceID; Root = ($_.DeviceID + '\\\\'); DriveType = $_.DriveType; VolumeName = $_.VolumeName }","}","@($items) | ConvertTo-Json -Compress"].join(`
4
- `),o=Q(J(r));for(const n of o){const s=String(n.Root||"");if(!s)continue;const i=Number(n.DriveType||0),a=String(n.Name||s.replace(/[\\/]+$/,"")),f=String(n.VolumeName||"").trim();e.set(h(s,"win32"),{id:`drive-${a.replace(/[^a-z0-9]+/gi,"").toLowerCase()}`,label:f?`${f} (${a})`:Ut(a,i),path:s,kind:Bt(i),available:!0})}}catch{const r=u.win32.parse(t).root;e.set(h(r,"win32"),{id:"drive-system",label:`系统盘 (${r.replace(/\\$/,"")})`,path:r,kind:"fixed",available:!0})}return[...e.values()]}function It(t,e){const r=C(t),n=l.readdirSync(r,{withFileTypes:!0}).filter(i=>i.isDirectory()&&!i.isSymbolicLink()&&(e||!i.name.startsWith("."))),s=n.slice(0,b).map(i=>({name:i.name,path:u.join(r,i.name),kind:"directory",hidden:i.name.startsWith("."),hasChildren:!0}));return s.sort((i,a)=>i.name.localeCompare(a.name,void 0,{numeric:!0,sensitivity:"base"})),X(r,s,n.length>b,"linux")}function Lt(t,e){const r=C(t),o=["$items = Get-ChildItem -LiteralPath $env:ACA_MACHINE_FS_PATH -Directory -Force -ErrorAction Stop | ForEach-Object {"," [PSCustomObject]@{ Name = $_.Name; FullName = $_.FullName; Attributes = $_.Attributes.ToString() }","}","@($items) | ConvertTo-Json -Compress"].join(`
5
- `),n=Q(J(o,{ACA_MACHINE_FS_PATH:r})),s=n.map(i=>{const a=String(i.Attributes||"");return{name:String(i.Name||""),path:String(i.FullName||""),kind:"directory",hidden:/Hidden|System/i.test(a),hasChildren:!0,reparsePoint:/ReparsePoint/i.test(a)}}).filter(i=>i.name&&i.path&&!i.reparsePoint&&(e||!i.hidden)).slice(0,b).sort((i,a)=>i.name.localeCompare(a.name,void 0,{numeric:!0,sensitivity:"base"}));return X(r,s,n.length>b,"win32")}function X(t,e,r,o){const n=o==="win32"?u.win32:u.posix,s=n.parse(t).root,i=h(t,o)===h(s,o)?null:n.dirname(t);return{platform:o,path:t,parentPath:i,breadcrumbs:Mt(t,o),readable:Y(t,l.constants.R_OK),writable:Y(t,l.constants.W_OK),items:e,truncated:r}}function Mt(t,e){const r=e==="win32"?u.win32:u.posix,o=r.parse(t),n=t.slice(o.root.length).split(/[\\/]+/).filter(Boolean),s=[{label:o.root.replace(/[\\/]+$/,"")||o.root,path:o.root}];let i=o.root;for(const a of n)i=r.join(i,a),s.push({label:a,path:i});return s}async function Ot(t){const e=String(t.workspaceId||"").trim(),r=String(t.name||"").trim(),o=t.projectType==="chat_room"?"chat_room":"project";if(!e||!r)throw new Error("项目名称和工作区不能为空。");const n=C(String(t.path||""));l.accessSync(n,l.constants.R_OK|l.constants.W_OK);const i=(await E("GET",`/api/projects?workspaceId=${encodeURIComponent(e)}`)).items.find(f=>h(f.root_path)===h(n)),a=i||(await E("POST","/api/projects",{projectId:F(),workspaceId:e,name:r,rootPath:n,source:"aica",projectType:o})).item;return rt(Gt(a)),{project:a,duplicate:!!i}}function Gt(t){return{projectId:t.project_id,workspaceId:t.workspace_id,name:t.name,rootPath:t.root_path}}function C(t){if(!t.trim()||!u.isAbsolute(t))throw new Error("必须选择绝对目录路径。");if(Ht(t),!l.statSync(t).isDirectory())throw new Error("选择的路径不是目录。");const r=l.realpathSync.native(t);return Wt(r),r}function p(t){const e=N(t),r=l.realpathSync.native(e);if(!l.statSync(r).isDirectory())throw new Error("项目根目录不存在。");return r}function N(t){const e=nt(t);if(!e||!u.isAbsolute(e))throw new Error("项目根目录无效。");return u.resolve(e)}function S(t){const e=t.replace(/\\/g,"/").replace(/^\/+|\/+$/g,"");if(!e)return"";if(e.includes("\0")||e.split("/").some(r=>!r||r==="."||r===".."))throw new Error("项目相对路径无效。");return e}function v(t,e,r){const o=e?u.join(t,...e.split("/")):t,n=l.realpathSync.native(o),s=u.relative(t,n);if(s.startsWith("..")||u.isAbsolute(s))throw new Error("目录超出项目范围。");const i=l.statSync(n);if(r&&!i.isDirectory())throw new Error("请求路径不是目录。");return n}function V(t,e){return u.relative(t,e).split(u.sep).join("/")}function Ht(t){const e=process.platform==="win32"?u.win32:u.posix;if(!R(process.platform).some(o=>{const n=String(o.path||"");if(!n)return!1;const s=e.relative(n,t);return s===""||!s.startsWith("..")&&!e.isAbsolute(s)}))throw new Error("目录不在允许浏览的位置内。")}function Wt(t){const e=process.platform==="win32"?u.win32:u.posix;if(!R(process.platform).some(o=>{const n=String(o.path||"");if(!n)return!1;const s=e.relative(n,t);return s===""||!s.startsWith("..")&&!e.isAbsolute(s)}))throw new Error("目录不在允许浏览的位置内。")}function Y(t,e){try{return l.accessSync(t,e),!0}catch{return!1}}function J(t,e={}){return y("powershell.exe",["-NoLogo","-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",windowsHide:!0,timeout:8e3,maxBuffer:4*1024*1024,env:{...process.env,...e}}).replace(/^\uFEFF/,"").trim()}function Q(t){if(!t)return[];const e=JSON.parse(t);return Array.isArray(e)?e.filter(r=>!!(r&&typeof r=="object")):e&&typeof e=="object"?[e]:[]}function Bt(t){return t===2?"removable":t===3?"fixed":t===4?"network":t===5?"optical":"drive"}function Ut(t,e){return e===2?`移动磁盘 (${t})`:e===4?`网络驱动器 (${t})`:e===5?`光驱 (${t})`:`本地磁盘 (${t})`}export{ft as cleanupWorktree,gt as commitProjectUploadTempFile,ut as commitWorktree,h as comparableMachinePath,bt as getProjectGitCommit,Pt as getProjectGitDiff,Et as getProjectGitLog,H as getProjectGitStatus,k as getWorktreeStatus,$t as listMachineDirectory,Nt as listMachineFilesystemRoots,dt as listProjectDirectory,ht as mutateProjectFiles,ie as startMachineFilesystemWorkerLoop,pt as uploadProjectFile};
3
+ [Diff 内容过大,已截断]`}function $t(){const t=process.platform,e=C(t);return{platform:t,roots:e}}function Tt(t){if(!t.directoryPath.trim())throw new Error("目录路径不能为空。");return process.platform==="win32"?Mt(t.directoryPath,!!t.includeHidden):Lt(t.directoryPath,!!t.includeHidden)}function h(t,e=process.platform){const r=e==="win32"?u.win32:u.posix,o=r.normalize(t),n=r.parse(o).root,s=o.length>n.length?o.replace(/[\\/]+$/,""):o;return e==="win32"?s.toLocaleLowerCase("en-US"):s}function Ft(){const t=l.realpathSync(I.homedir()),e=[{id:"home",label:"用户目录",path:t,kind:"home",available:!0}];return t!==u.parse(t).root&&e.push({id:"root",label:"文件系统",path:"/",kind:"root",available:!0}),e}function C(t){if(b?.platform===t&&b.expiresAtMs>Date.now())return b.roots;const e=t==="win32"?It():Ft();return b={platform:t,roots:e,expiresAtMs:Date.now()+lt},e}function It(){const t=l.realpathSync.native(I.homedir()),e=new Map;e.set(h(t,"win32"),{id:"home",label:"用户目录",path:t,kind:"home",available:!0});try{const r=["$items = Get-CimInstance Win32_LogicalDisk | ForEach-Object {"," [PSCustomObject]@{ Name = $_.DeviceID; Root = ($_.DeviceID + '\\\\'); DriveType = $_.DriveType; VolumeName = $_.VolumeName }","}","@($items) | ConvertTo-Json -Compress"].join(`
4
+ `),o=Q(J(r));for(const n of o){const s=String(n.Root||"");if(!s)continue;const i=Number(n.DriveType||0),a=String(n.Name||s.replace(/[\\/]+$/,"")),d=String(n.VolumeName||"").trim();e.set(h(s,"win32"),{id:`drive-${a.replace(/[^a-z0-9]+/gi,"").toLowerCase()}`,label:d?`${d} (${a})`:zt(a,i),path:s,kind:Ut(i),available:!0})}}catch{const r=u.win32.parse(t).root;e.set(h(r,"win32"),{id:"drive-system",label:`系统盘 (${r.replace(/\\$/,"")})`,path:r,kind:"fixed",available:!0})}return[...e.values()]}function Lt(t,e){const r=R(t),n=l.readdirSync(r,{withFileTypes:!0}).filter(i=>i.isDirectory()&&!i.isSymbolicLink()&&(e||!i.name.startsWith("."))),s=n.slice(0,x).map(i=>({name:i.name,path:u.join(r,i.name),kind:"directory",hidden:i.name.startsWith("."),hasChildren:!0}));return s.sort((i,a)=>i.name.localeCompare(a.name,void 0,{numeric:!0,sensitivity:"base"})),X(r,s,n.length>x,"linux")}function Mt(t,e){const r=R(t),o=["$items = Get-ChildItem -LiteralPath $env:ACA_MACHINE_FS_PATH -Directory -Force -ErrorAction Stop | ForEach-Object {"," [PSCustomObject]@{ Name = $_.Name; FullName = $_.FullName; Attributes = $_.Attributes.ToString() }","}","@($items) | ConvertTo-Json -Compress"].join(`
5
+ `),n=Q(J(o,{ACA_MACHINE_FS_PATH:r})),s=n.map(i=>{const a=String(i.Attributes||"");return{name:String(i.Name||""),path:String(i.FullName||""),kind:"directory",hidden:/Hidden|System/i.test(a),hasChildren:!0,reparsePoint:/ReparsePoint/i.test(a)}}).filter(i=>i.name&&i.path&&!i.reparsePoint&&(e||!i.hidden)).slice(0,x).sort((i,a)=>i.name.localeCompare(a.name,void 0,{numeric:!0,sensitivity:"base"}));return X(r,s,n.length>x,"win32")}function X(t,e,r,o){const n=o==="win32"?u.win32:u.posix,s=n.parse(t).root,i=h(t,o)===h(s,o)?null:n.dirname(t);return{platform:o,path:t,parentPath:i,breadcrumbs:Ot(t,o),readable:Y(t,l.constants.R_OK),writable:Y(t,l.constants.W_OK),items:e,truncated:r}}function Ot(t,e){const r=e==="win32"?u.win32:u.posix,o=r.parse(t),n=t.slice(o.root.length).split(/[\\/]+/).filter(Boolean),s=[{label:o.root.replace(/[\\/]+$/,"")||o.root,path:o.root}];let i=o.root;for(const a of n)i=r.join(i,a),s.push({label:a,path:i});return s}async function Ht(t){const e=String(t.workspaceId||"").trim(),r=String(t.name||"").trim(),o=t.projectType==="chat_room"?"chat_room":"project";if(!e||!r)throw new Error("项目名称和工作区不能为空。");const n=R(String(t.path||""));l.accessSync(n,l.constants.R_OK|l.constants.W_OK);const i=(await E("GET",`/api/projects?workspaceId=${encodeURIComponent(e)}`)).items.find(d=>h(d.root_path)===h(n)),a=i||(await E("POST","/api/projects",{projectId:F(),workspaceId:e,name:r,rootPath:n,source:"aica",projectType:o})).item;return ot(Gt(a)),{project:a,duplicate:!!i}}function Gt(t){return{projectId:t.project_id,workspaceId:t.workspace_id,name:t.name,rootPath:t.root_path}}function R(t){if(!t.trim()||!u.isAbsolute(t))throw new Error("必须选择绝对目录路径。");if(Wt(t),!l.statSync(t).isDirectory())throw new Error("选择的路径不是目录。");const r=l.realpathSync.native(t);return Bt(r),r}function p(t){const e=N(t),r=l.realpathSync.native(e);if(!l.statSync(r).isDirectory())throw new Error("项目根目录不存在。");return r}function N(t){const e=it(t);if(!e||!u.isAbsolute(e))throw new Error("项目根目录无效。");return u.resolve(e)}function S(t){const e=t.replace(/\\/g,"/").replace(/^\/+|\/+$/g,"");if(!e)return"";if(e.includes("\0")||e.split("/").some(r=>!r||r==="."||r===".."))throw new Error("项目相对路径无效。");return e}function v(t,e,r){const o=e?u.join(t,...e.split("/")):t,n=l.realpathSync.native(o),s=u.relative(t,n);if(s.startsWith("..")||u.isAbsolute(s))throw new Error("目录超出项目范围。");const i=l.statSync(n);if(r&&!i.isDirectory())throw new Error("请求路径不是目录。");return n}function V(t,e){return u.relative(t,e).split(u.sep).join("/")}function Wt(t){const e=process.platform==="win32"?u.win32:u.posix;if(!C(process.platform).some(o=>{const n=String(o.path||"");if(!n)return!1;const s=e.relative(n,t);return s===""||!s.startsWith("..")&&!e.isAbsolute(s)}))throw new Error("目录不在允许浏览的位置内。")}function Bt(t){const e=process.platform==="win32"?u.win32:u.posix;if(!C(process.platform).some(o=>{const n=String(o.path||"");if(!n)return!1;const s=e.relative(n,t);return s===""||!s.startsWith("..")&&!e.isAbsolute(s)}))throw new Error("目录不在允许浏览的位置内。")}function Y(t,e){try{return l.accessSync(t,e),!0}catch{return!1}}function J(t,e={}){return y("powershell.exe",["-NoLogo","-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",windowsHide:!0,timeout:8e3,maxBuffer:4*1024*1024,env:{...process.env,...e}}).replace(/^\uFEFF/,"").trim()}function Q(t){if(!t)return[];const e=JSON.parse(t);return Array.isArray(e)?e.filter(r=>!!(r&&typeof r=="object")):e&&typeof e=="object"?[e]:[]}function Ut(t){return t===2?"removable":t===3?"fixed":t===4?"network":t===5?"optical":"drive"}function zt(t,e){return e===2?`移动磁盘 (${t})`:e===4?`网络驱动器 (${t})`:e===5?`光驱 (${t})`:`本地磁盘 (${t})`}export{ft as cleanupWorktree,St as commitProjectUploadTempFile,dt as commitWorktree,h as comparableMachinePath,bt as getProjectGitCommit,Et as getProjectGitDiff,xt as getProjectGitLog,G as getProjectGitStatus,k as getWorktreeStatus,Tt as listMachineDirectory,$t as listMachineFilesystemRoots,mt as listProjectDirectory,wt as mutateProjectFiles,ae as startMachineFilesystemWorkerLoop,ht as uploadProjectFile};
@@ -1 +1 @@
1
- import{execFileSync as m}from"node:child_process";import i from"node:fs";import l from"node:os";import u from"node:path";import{resolveCodexPath as f}from"../acp/providers/codex/codex-process.js";const d=360*60*1e3,p="aica-provider-probe-",E=3600*1e3;let c=null;function A(){const t=Date.now();if(c&&c.expiresAtMs>t)return c.items;const e={codex:s(f()),mimo:s(process.env.ACA_MIMO_COMMAND||"mimo"),opencode:s(process.env.ACA_OPENCODE_COMMAND||"opencode")};return c={expiresAtMs:t+d,items:e},e}function s(t){const e=Date.now();let r=null;try{_(e),r=i.mkdtempSync(u.join(l.tmpdir(),p));const o=m(t,["--version"],{encoding:"utf8",timeout:8e3,maxBuffer:256*1024,stdio:["ignore","pipe","pipe"],env:{...process.env,TMPDIR:r,TEMP:r,TMP:r}});return{available:!0,status:"ready",version:v(o),checkedAtMs:e,errorCode:null}}catch(o){const n=y(o);return{available:!1,status:n==="ENOENT"?"unavailable":"error",version:null,checkedAtMs:e,errorCode:n==="ENOENT"?"not_installed":"probe_failed"}}finally{r&&i.rmSync(r,{recursive:!0,force:!0})}}function _(t){const e=l.tmpdir();let r;try{r=i.readdirSync(e).filter(o=>o.startsWith(p))}catch{return}for(const o of r){const n=u.join(e,o);try{const a=i.lstatSync(n);if(!a.isDirectory()||t-a.mtimeMs<E)continue;i.rmSync(n,{recursive:!0,force:!0})}catch{}}}function v(t){const e=t.split(/\r?\n/).map(r=>r.trim()).find(Boolean);return e?e.slice(0,120):null}function y(t){if(!t||typeof t!="object")return null;const e=t.code;return typeof e=="string"?e:null}export{s as probeProvider,A as providerHealthSnapshot};
1
+ import{execFileSync as m}from"node:child_process";import i from"node:fs";import l from"node:os";import u from"node:path";import{resolveCodexPath as f}from"../acp/providers/codex/codex-process.js";const d=360*60*1e3,p="aica-provider-probe-",E=3600*1e3;let c=null;function A(){const t=Date.now();if(c&&c.expiresAtMs>t)return c.items;const e={codex:s(f()),mimo:s(process.env.ACA_MIMO_COMMAND||"mimo"),opencode:s(process.env.ACA_OPENCODE_COMMAND||"opencode")};return c={expiresAtMs:t+d,items:e},e}function s(t){const e=Date.now();let r=null;try{_(e),r=i.mkdtempSync(u.join(l.tmpdir(),p));const o=m(t,["--version"],{windowsHide:!0,encoding:"utf8",timeout:8e3,maxBuffer:256*1024,stdio:["ignore","pipe","pipe"],env:{...process.env,TMPDIR:r,TEMP:r,TMP:r}});return{available:!0,status:"ready",version:v(o),checkedAtMs:e,errorCode:null}}catch(o){const n=y(o);return{available:!1,status:n==="ENOENT"?"unavailable":"error",version:null,checkedAtMs:e,errorCode:n==="ENOENT"?"not_installed":"probe_failed"}}finally{r&&i.rmSync(r,{recursive:!0,force:!0})}}function _(t){const e=l.tmpdir();let r;try{r=i.readdirSync(e).filter(o=>o.startsWith(p))}catch{return}for(const o of r){const n=u.join(e,o);try{const a=i.lstatSync(n);if(!a.isDirectory()||t-a.mtimeMs<E)continue;i.rmSync(n,{recursive:!0,force:!0})}catch{}}}function v(t){const e=t.split(/\r?\n/).map(r=>r.trim()).find(Boolean);return e?e.slice(0,120):null}function y(t){if(!t||typeof t!="object")return null;const e=t.code;return typeof e=="string"?e:null}export{s as probeProvider,A as providerHealthSnapshot};
@@ -1 +1 @@
1
- import o from"node:fs";import r from"node:path";import{createRequire as l}from"node:module";import{getAsset as c,isSea as m}from"node:sea";import{getAcaHome as s}from"../paths.js";class p extends Error{code="TERMINAL_DEPENDENCY_UNAVAILABLE";installation;constructor(e){super("终端组件 node-pty 未安装或无法加载。",{cause:e}),this.name="TerminalDependencyError";const t=r.resolve(s(),"terminal-deps"),n=process.platform==="win32"?`'${t.replaceAll("'","''")}'`:`'${t.replaceAll("'","'\\''")}'`;this.installation={command:`npm install --prefix ${n} --no-save --package-lock=false node-pty@1.1.0`,shell:process.platform==="win32"?"PowerShell":"Shell",prerequisites:process.platform==="linux"?"若安装提示编译工具缺失,请先安装 Python 3、make 和 C++ 编译器。Debian/Ubuntu 可由管理员执行:apt-get install -y python3 build-essential。":process.platform==="darwin"?"若安装需要编译,请先安装 Python 3 和 Xcode Command Line Tools(xcode-select --install)。":"若安装需要编译,请先安装 Python 和 Visual Studio 的 C++ 构建工具。"}}}async function x(){const i=l(m()?process.execPath:import.meta.url);try{return m()?d():i("node-pty")}catch(e){const t=r.resolve(s(),"terminal-deps","node_modules","node-pty");try{return i(t)}catch(n){throw new p(o.existsSync(t)?n:e)}}}function d(){const i=JSON.parse(c("terminal-manifest","utf8")),e=r.join(s(),"native",`pty-${i.hash}`);if(!o.existsSync(r.join(e,".ready"))){o.mkdirSync(r.dirname(e),{recursive:!0,mode:448});const t=o.mkdtempSync(`${e}-`);try{for(const n of i.files){const a=r.join(t,n.name);o.mkdirSync(r.dirname(a),{recursive:!0}),o.writeFileSync(a,Buffer.from(c(`terminal/${n.name}`)),{mode:n.executable?448:384})}o.writeFileSync(r.join(t,".ready"),"");try{o.renameSync(t,e)}catch(n){if(!o.existsSync(r.join(e,".ready")))throw n}}finally{o.rmSync(t,{recursive:!0,force:!0})}}return l(r.join(e,"package.json"))(r.join(e,"lib","index.js"))}export{p as TerminalDependencyError,x as loadPty};
1
+ import t from"node:fs";import r from"node:path";import{createRequire as m}from"node:module";import{getAsset as p,isSea as d}from"node:sea";import{getAcaHome as a}from"../paths.js";import{hideWindowsPtyConsole as l}from"./windows-console.js";class y extends Error{code="TERMINAL_DEPENDENCY_UNAVAILABLE";installation;constructor(e){super("终端组件 node-pty 未安装或无法加载。",{cause:e}),this.name="TerminalDependencyError";const o=r.resolve(a(),"terminal-deps"),i=process.platform==="win32"?`'${o.replaceAll("'","''")}'`:`'${o.replaceAll("'","'\\''")}'`;this.installation={command:`npm install --prefix ${i} --no-save --package-lock=false node-pty@1.1.0`,shell:process.platform==="win32"?"PowerShell":"Shell",prerequisites:process.platform==="linux"?"若安装提示编译工具缺失,请先安装 Python 3、make 和 C++ 编译器。Debian/Ubuntu 可由管理员执行:apt-get install -y python3 build-essential。":process.platform==="darwin"?"若安装需要编译,请先安装 Python 3 和 Xcode Command Line Tools(xcode-select --install)。":"若安装需要编译,请先安装 Python 和 Visual Studio 的 C++ 构建工具。"}}}async function j(){const n=m(d()?process.execPath:import.meta.url);try{return d()?u():l(n("node-pty"),n.resolve("node-pty"))}catch(e){const o=r.resolve(a(),"terminal-deps","node_modules","node-pty");try{return l(n(o),n.resolve(o))}catch(i){throw new y(t.existsSync(o)?i:e)}}}function u(){const n=JSON.parse(p("terminal-manifest","utf8")),e=r.join(a(),"native",`pty-${n.hash}`);if(!t.existsSync(r.join(e,".ready"))){t.mkdirSync(r.dirname(e),{recursive:!0,mode:448});const i=t.mkdtempSync(`${e}-`);try{for(const s of n.files){const c=r.join(i,s.name);t.mkdirSync(r.dirname(c),{recursive:!0}),t.writeFileSync(c,Buffer.from(p(`terminal/${s.name}`)),{mode:s.executable?448:384})}t.writeFileSync(r.join(i,".ready"),"");try{t.renameSync(i,e)}catch(s){if(!t.existsSync(r.join(e,".ready")))throw s}}finally{t.rmSync(i,{recursive:!0,force:!0})}}const o=r.join(e,"lib","index.js");return l(m(r.join(e,"package.json"))(o),o)}export{y as TerminalDependencyError,j as loadPty};
@@ -0,0 +1 @@
1
+ import{fork as p}from"node:child_process";import l from"node:fs";import a from"node:path";function C(o,t,u=process.platform){if(u!=="win32")return o;const s=a.join(a.dirname(t),"conpty_console_list_agent.js");return l.existsSync(s)?{...o,spawn:(...r)=>{const i=o.spawn(...r),e=i._agent;return e?._useConpty&&!e._useConptyDll&&typeof e._getConsoleProcessList=="function"&&(e._getConsoleProcessList=()=>_(s,e._innerPid)),i}}:o}function _(o,t,u=p){return new Promise(s=>{let r;try{const c={windowsHide:!0,stdio:[0,1,2,"ipc"]};r=u(o,[String(t)],c)}catch{s([t]);return}let i=!1;const e=(c,n=!1)=>{if(!i){if(i=!0,clearTimeout(m),n)try{r.kill()}catch{}s(c)}},m=setTimeout(()=>e([t],!0),5e3);r.once("message",c=>{const n=c?.consoleProcessList;Array.isArray(n)&&n.length&&n.every(f=>Number.isInteger(f)&&f>0)?e(n):e([t],!0)}),r.once("error",()=>e([t],!0)),r.once("exit",()=>e([t]))})}export{C as hideWindowsPtyConsole,_ as readConsoleProcessList};
@@ -1 +1 @@
1
- import{execFileSync as d}from"node:child_process";import w from"node:crypto";import c from"node:fs";import a from"node:path";import{getAcaHome as f}from"./paths.js";import{expandWorkerRuntimePath as h}from"./worker-runtime-paths.js";function x(e){const t=e.worktree.worktree_id;if(!t||e.worktree.worktree_status==="disabled")return{cwd:e.projectRoot,usedWorktree:!1};const s=e.worktree.worktree_path?a.resolve(h(e.worktree.worktree_path)):null;if(e.worktree.worktree_status==="active"&&s&&c.existsSync(s))return{cwd:s,usedWorktree:!0,worktreeId:t,status:"active",baseCommit:e.worktree.worktree_base_commit??null,branchName:e.worktree.worktree_branch_name??null,baseBranch:e.worktree.worktree_base_branch??null};const r=a.resolve(e.projectRoot),l=k(e.projectId??"project"),u=k(e.sessionId),o=a.join(f(),"worktrees",l,u),i=e.worktree.worktree_base_branch||"HEAD",n=e.worktree.worktree_branch_name||`aca/session-${u}`,m=b(r);return c.mkdirSync(a.dirname(o),{recursive:!0}),c.existsSync(o)?{cwd:o,usedWorktree:!0,worktreeId:t,status:"active",baseCommit:m,branchName:n,baseBranch:i,raw:{source:"aca-client",reusedExistingPath:!0,projectRoot:r}}:m?(d("git",["worktree","add","-B",n,o,i],{cwd:r,stdio:"pipe"}),{cwd:o,usedWorktree:!0,worktreeId:t,status:"active",baseCommit:m,branchName:n,baseBranch:i,raw:{source:"aca-client",mode:"git-worktree",projectRoot:r}}):(c.mkdirSync(o,{recursive:!0}),p(r,o),{cwd:o,usedWorktree:!0,worktreeId:t,status:"fallback-directory",baseCommit:null,branchName:n,baseBranch:i,raw:{source:"aca-client",mode:"fallback-directory",projectRoot:r,fallbackReason:"git repository has no commits"}})}function b(e){try{return d("git",["rev-parse","HEAD"],{cwd:e,encoding:"utf8",stdio:"pipe"}).trim()||null}catch{return null}}function p(e,t){c.cpSync(e,t,{recursive:!0,filter:s=>{const r=a.relative(e,s);if(!r)return!0;const l=r.split(a.sep)[0];return![".git","node_modules","dist",".aca",".aica"].includes(l)}})}function k(e){return e.replace(/[^a-zA-Z0-9._-]+/g,"-").slice(0,80)||w.randomUUID()}export{x as prepareLocalWorktree};
1
+ import{execFileSync as m}from"node:child_process";import k from"node:crypto";import c from"node:fs";import s from"node:path";import{getAcaHome as f}from"./paths.js";import{expandWorkerRuntimePath as h}from"./worker-runtime-paths.js";function x(e){const t=e.worktree.worktree_id;if(!t||e.worktree.worktree_status==="disabled")return{cwd:e.projectRoot,usedWorktree:!1};const a=e.worktree.worktree_path?s.resolve(h(e.worktree.worktree_path)):null;if(e.worktree.worktree_status==="active"&&a&&c.existsSync(a))return{cwd:a,usedWorktree:!0,worktreeId:t,status:"active",baseCommit:e.worktree.worktree_base_commit??null,branchName:e.worktree.worktree_branch_name??null,baseBranch:e.worktree.worktree_base_branch??null};const r=s.resolve(e.projectRoot),d=w(e.projectId??"project"),l=w(e.sessionId),o=s.join(f(),"worktrees",d,l),i=e.worktree.worktree_base_branch||"HEAD",n=e.worktree.worktree_branch_name||`aca/session-${l}`,u=b(r);return c.mkdirSync(s.dirname(o),{recursive:!0}),c.existsSync(o)?{cwd:o,usedWorktree:!0,worktreeId:t,status:"active",baseCommit:u,branchName:n,baseBranch:i,raw:{source:"aca-client",reusedExistingPath:!0,projectRoot:r}}:u?(m("git",["worktree","add","-B",n,o,i],{windowsHide:!0,cwd:r,stdio:"pipe"}),{cwd:o,usedWorktree:!0,worktreeId:t,status:"active",baseCommit:u,branchName:n,baseBranch:i,raw:{source:"aca-client",mode:"git-worktree",projectRoot:r}}):(c.mkdirSync(o,{recursive:!0}),p(r,o),{cwd:o,usedWorktree:!0,worktreeId:t,status:"fallback-directory",baseCommit:null,branchName:n,baseBranch:i,raw:{source:"aca-client",mode:"fallback-directory",projectRoot:r,fallbackReason:"git repository has no commits"}})}function b(e){try{return m("git",["rev-parse","HEAD"],{windowsHide:!0,cwd:e,encoding:"utf8",stdio:"pipe"}).trim()||null}catch{return null}}function p(e,t){c.cpSync(e,t,{recursive:!0,filter:a=>{const r=s.relative(e,a);if(!r)return!0;const d=r.split(s.sep)[0];return![".git","node_modules","dist",".aca",".aica"].includes(d)}})}function w(e){return e.replace(/[^a-zA-Z0-9._-]+/g,"-").slice(0,80)||k.randomUUID()}export{x as prepareLocalWorktree};
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- const o="0.1.76";export{o as AICA_VERSION};
1
+ const o="0.1.78";export{o as AICA_VERSION};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuandc/aica",
3
- "version": "0.1.76",
3
+ "version": "0.1.78",
4
4
  "description": "AICA remote Agent worker",
5
5
  "author": "yuandc",
6
6
  "type": "module",