import{spawn as T,execSync as N}from"child_process";import{existsSync as l,mkdirSync as O,readdirSync as S,statSync as j,readFileSync as C}from"fs";import{resolve as x,join as u,basename as R}from"path";var $=".zibby/repos";function E(a){let n=String(a??"");for(let e of[process.env.GITHUB_TOKEN,process.env.GITLAB_TOKEN])e&&(n=n.split(e).join("***"));return n.replace(/x-access-token:[^@\s]*@/g,"x-access-token:***@").replace(/oauth2:[^@\s]*@/g,"oauth2:***@").replace(/https?:\/\/[^/@\s:]+:[^@\s]+@/g,e=>e.replace(/:[^@\s]+@/,":***@"))}function G(a,n,e,o,s="clone"){try{a(`git -C "${n}" remote set-url origin "${e}"`,{stdio:"pipe"})}catch(t){let c=String(t?.message||t);o&&(c=c.split(o).join("***")),console.error(`[${s}] WARNING: failed to strip token from .git/config: ${c}`)}}function w(a,n,e={}){return new Promise((o,s)=>{let t=T(a,{cwd:n,shell:!0,env:{...process.env,GIT_TERMINAL_PROMPT:"0",...e}}),c="",f="";t.stdout.on("data",i=>{c+=i.toString()}),t.stderr.on("data",i=>{f+=i.toString()}),t.on("close",i=>{i!==0?s(new Error(`Exit ${i}: ${f.trim()||c.trim()}`)):o(c.trim())}),t.on("error",i=>s(i))})}var F={id:"git",description:"Clone and manage git repositories for codebase analysis",envKeys:["GITHUB_TOKEN","GITLAB_TOKEN"],promptFragment:`## Git Repositories
You can clone and explore git repositories locally for codebase analysis:
- git_checkout: Clone a repo (or pull if already cloned). Supports GitHub and GitLab with auto-auth.
- git_list_repos: List locally cloned repos
- git_explore: Quick overview of a cloned repo's structure (key files, package.json, routes, etc.)

When a test ticket lacks context, use this workflow:
1. Clone the relevant repo with git_checkout
2. Use git_explore to understand the project structure
3. Use shell commands (grep, cat) to read specific files for deeper understanding
4. Use GitHub/GitLab skills to read related PRs and commits
5. Build well-informed test specs and save them to files before running tests`,resolve(){return null},async handleToolCall(a,n,e){let o=e?.options?.workspace||process.cwd();try{switch(a){case"git_checkout":return await L(n,o);case"git_list_repos":return A(n,o);case"git_explore":return D(n,o);default:return JSON.stringify({error:`Unknown tool: ${a}`})}}catch(s){return JSON.stringify({error:E(s.message)})}},tools:[{name:"git_checkout",description:"Clone a git repository locally (or pull latest if already cloned). Auto-authenticates with GitHub/GitLab tokens if available.",input_schema:{type:"object",properties:{url:{type:"string",description:'Repository URL (e.g. "https://github.com/org/repo" or "org/repo" shorthand for GitHub)'},branch:{type:"string",description:"Branch to checkout (default: repo default branch)"},shallow:{type:"boolean",description:"Shallow clone with depth 1 (default: true, faster)"},name:{type:"string",description:"Local directory name override (default: repo name from URL)"}},required:["url"]}},{name:"git_list_repos",description:"List locally cloned repositories",input_schema:{type:"object",properties:{}}},{name:"git_explore",description:"Quick structural overview of a cloned repo: key files, package.json info, directory tree (top 2 levels), detected framework/language",input_schema:{type:"object",properties:{repo:{type:"string",description:"Repo name (as listed by git_list_repos)"},depth:{type:"number",description:"Directory tree depth (default: 2)"}},required:["repo"]}}]};async function L(a,n){let{url:e,branch:o,shallow:s=!0,name:t}=a;!e.includes("://")&&!e.startsWith("git@")&&(e=`https://github.com/${e}`);let c=t||R(e.replace(/\.git$/,"")),f=x(n,$);O(f,{recursive:!0});let i=u(f,c),g=e,h=process.env.GITHUB_TOKEN,m=process.env.GITLAB_TOKEN,k=process.env.GITLAB_URL;if(e.includes("github.com")&&h)g=e.replace("https://github.com",`https://x-access-token:${h}@github.com`);else if(m&&k)try{let d=new URL(k).host;e.includes(d)&&(g=e.replace(`https://${d}`,`https://oauth2:${m}@${d}`))}catch{}if(l(u(i,".git"))){let d=o?`git -C "${i}" fetch "${g}" ${o} && git -C "${i}" checkout ${o} && git -C "${i}" merge --ff-only FETCH_HEAD`:`git -C "${i}" pull "${g}"`;await w(d,n);let b=await w(`git -C "${i}" log -1 --format="%h %s"`,n);return JSON.stringify({action:"updated",repo:c,path:i,branch:o||"default",head:b})}let r=["git","clone"];s&&r.push("--depth","1"),o&&r.push("--branch",o),r.push(`"${g}"`,`"${i}"`),await w(r.join(" "),n),G(N,i,e,h||m,"git_checkout");let _=await w(`git -C "${i}" log -1 --format="%h %s"`,n);return JSON.stringify({action:"cloned",repo:c,path:i,branch:o||"default",shallow:s,head:_})}function A(a,n){let e=x(n,$);if(!l(e))return JSON.stringify({repos:[],message:"No repos cloned yet"});let o=[];for(let s of S(e,{withFileTypes:!0})){if(!s.isDirectory())continue;let t=u(e,s.name);if(!l(u(t,".git")))continue;let c=j(t);o.push({name:s.name,path:t,lastModified:c.mtime.toISOString()})}return JSON.stringify({repos:o,total:o.length,directory:e})}function D(a,n){let{repo:e,depth:o=2}=a,s=x(n,$,e);if(!l(s))return JSON.stringify({error:`Repo not found: ${e}. Run git_checkout first.`});let t={repo:e,path:s},c=u(s,"package.json");if(l(c))try{let r=JSON.parse(C(c,"utf-8"));t.packageJson={name:r.name,version:r.version,scripts:r.scripts?Object.keys(r.scripts):[],dependencies:r.dependencies?Object.keys(r.dependencies).slice(0,30):[],devDependencies:r.devDependencies?Object.keys(r.devDependencies).slice(0,20):[]},r.dependencies?.react?t.framework="React":r.dependencies?.next?t.framework="Next.js":r.dependencies?.vue?t.framework="Vue":r.dependencies?.angular?t.framework="Angular":r.dependencies?.express?t.framework="Express":r.dependencies?.fastify&&(t.framework="Fastify")}catch{}let f=u(s,"pyproject.toml");l(f)&&(t.language="Python");let i=u(s,"go.mod");l(i)&&(t.language="Go");let g=u(s,"Cargo.toml");l(g)&&(t.language="Rust"),l(c)&&(t.language=t.language||"JavaScript/TypeScript");let h=[];function m(r,_,d){if(d>o)return;let b;try{b=S(r,{withFileTypes:!0})}catch{return}let v=b.filter(p=>!p.name.startsWith(".")&&p.name!=="node_modules"&&p.name!=="__pycache__"&&p.name!=="dist"&&p.name!=="build"&&p.name!==".git").sort((p,y)=>p.isDirectory()!==y.isDirectory()?p.isDirectory()?-1:1:p.name.localeCompare(y.name));for(let p of v){let y=p.isDirectory();h.push(`${_}${y?"\u{1F4C1}":"\u{1F4C4}"} ${p.name}`),y&&d<o&&m(u(r,p.name),`${_}  `,d+1)}}m(s,"",1),t.tree=h.slice(0,80),h.length>80&&(t.treeTruncated=!0);let k=["README.md","README.rst","src/App.tsx","src/App.jsx","src/App.js","src/routes.tsx","src/routes.js","app/routes.tsx","app/routes.js","src/index.tsx","src/index.ts","src/main.tsx","src/main.ts","pages/_app.tsx","pages/_app.js","app/layout.tsx","docker-compose.yml","Dockerfile",".env.example"];return t.keyFilesFound=k.filter(r=>l(u(s,r))),JSON.stringify(t)}export{F as gitSkill,G as scrubClonedRemoteSync};
