| 4711 | |
| 4712 | Technical details: ${J.message}`)}throw Error(`Failed to download marketplace from ${$}: ${d6(J)}`)}Cb(z,"Validating marketplace data");let j=de().safeParse(O.data);if(!j.success)throw KD("marketplace_url",q,"failure",performance.now()-w,"invalid_schema"),new hT(`Invalid marketplace schema from URL: ${j.error.issues.map((J)=>`${J.path.join(".")}: ${J.message}`).join(", ")}`,$,O.data);KD("marketplace_url",q,"success",performance.now()-w),Cb(z,"Saving marketplace to cache");let H=dX(K,"..");await Y.mkdir(H),$j(K,g6(j.data,null,2),{encoding:"utf-8",flush:!0})}function azY(q){return q.source==="github"?q.repo.replace("/","-"):q.source==="npm"?q.package.replace("@","").replace("/","-"):q.source==="file"?rfK(q.path).replace(".json",""):q.source==="directory"?rfK(q.path):"temp_"+Date.now()}async function m17(q,K){let z=await X8().readFile(q,{encoding:"utf-8"}),Y;try{Y=r8(z)}catch(A){throw new hT(`Invalid JSON in ${q}: ${d6(A)}`,q,z)}let $=K.safeParse(Y);if(!$.success)throw new hT(`Invalid schema: ${q} ${$.error?.issues.map((A)=>`${A.path.join(".")}: ${A.message}`).join(", ")}`,q,Y);return $.data}async function p17(q,K){let _=X8(),z=sK6();await _.mkdir(z);let Y,$,A=!1,O=azY(q);try{switch(q.source){case"url":{Y=dX(z,`${O}.json`),A=!0,await efK(q.url,Y,q.headers,K),$=Y;break}case"github":{let M=`git@github.com:${q.repo}.git`,X=`https://github.com/${q.repo}.git`;Y=dX(z,O),A=!0;let P=null;if(await tfK()){Cb(K,`Cloning via SSH: ${M}`);try{await Ba(M,Y,q.ref,q.sparsePaths,K)}catch(D){P=x1(D),H6(P),Cb(K,`SSH clone failed, retrying with HTTPS: ${X}`),N(`SSH clone failed for ${q.repo} despite SSH being configured, falling back to HTTPS`,{level:"info"}),await _.rm(Y,{recursive:!0,force:!0});try{await Ba(X,Y,q.ref,q.sparsePaths,K),P=null}catch(f){P=x1(f),H6(P)}}}else{Cb(K,`SSH not configured, cloning via HTTPS: ${X}`),N(`SSH not configured for GitHub, using HTTPS for ${q.repo}`,{level:"info"});try{await Ba(X,Y,q.ref,q.sparsePaths,K)}catch(D){P=x1(D),H6(P),Cb(K,`HTTPS clone failed, retrying with SSH: ${M}`),N(`HTTPS clone failed for ${q.repo} (${P.message}), falling back to SSH`,{level:"info"}),await _.rm(Y,{recursive:!0,force:!0});try{await Ba(M,Y,q.ref,q.sparsePaths,K),P=null}catch(f){P=x1(f),H6(P)}}}if(P)throw P;$=dX(Y,q.path||".claude-plugin/marketplace.json");break}case"git":{Y=dX(z,O),A=!0,await Ba(q.url,Y,q.ref,q.sparsePaths,K),$=dX(Y,q.path||".claude-plugin/marketplace.json");break}case"npm":throw Error("NPM marketplace sources not yet implemented");case"file":{let M=Kd(q.path);$=M,Y=u17(u17(M)),A=!1;break}case"directory":{let M=Kd(q.path);$=dX(M,".claude-plugin","marketplace.json"),Y=M,A=!1;break}case"settings":{Y=dX(z,q.name),$=dX(Y,".claude-plugin","marketplace.json"),A=!1,await _.mkdir(u17($)),await FzY($,g6({name:q.name,owner:q.owner??{name:"settings"},plugins:q.plugins},null,2));break}default:throw Error("Unsupported marketplace source type")}N(`Reading marketplace from ${$}`);let w;try{w=await m17($,de())}catch(M){if(_7(M))throw Error(`Marketplace file not found at ${$}`);throw Error(`Failed to parse marketplace file at ${$}: ${d6(M)}`)}let j=dX(z,w.name),H=Kd(j),J=Kd(z);if(!H.startsWith(J+fB8))throw Error(`Marketplace name '${w.name}' resolves to a path outside the cache directory`);if(Y!==j&&!SB(q))try{try{K?.("Cleaning up old marketplace cache…")}catch(M){N(`Progress callback error: ${d6(M)}`,{level:"warn"})}await _.rm(j,{recursive:!0,force:!0}),await _.rename(Y,j),Y=j,A=!1}catch(M){let X=d6(M);throw Error(`Failed to finalize marketplace cache. Please manually delete the directory at ${j} if it exists and try again. |
| 4713 | |
| 4714 | Technical details: ${X}`)}return{marketplace:w,cachePath:Y}}catch(w){if(A&&Y&&!SB(q))try{await _.rm(Y,{recursive:!0,force:!0})}catch(j){N(`Warning: Failed to clean up temporary marketplace cache at ${Y}: ${d6(j)}`,{level:"warn"})}throw w}}async function Yd(q,K){let _=q;if(SB(q)&&!sfK(q.path))_={...q,path:Kd(q.path)};if(!NH6(_)){if(S18(_))throw Error(`Marketplace source '${yH6(_)}' is blocked by enterprise policy.`);let j=aK6()||[],H=FfK(),J=b17(_),M=`Marketplace source '${yH6(_)}'`;if(J)M+=` (${J})`;if(M+=" is blocked by enterprise policy.",j.length>0)M+=` Allowed sources: ${j.map((X)=>yH6(X)).join(", ")}`;else M+=" No external marketplaces are allowed.";if(_.source==="github"&&H.length>0)M+=` |
| 4715 | |
| 4716 | Tip: The shorthand "${_.repo}" assumes github.com. For internal GitHub Enterprise, use the full URL: |
| 4717 | git@your-github-host.com:${_.repo}.git`;throw Error(M)}let z=await r_();for(let[j,H]of Object.entries(z))if(QJ(H.source,_))return N(`Source already materialized as '${j}', skipping clone`),{name:j,alreadyMaterialized:!0,resolvedSource:_};let{marketplace:Y,cachePath:$}=await p17(_,K),A=ah7(Y.name,_);if(A)throw Error(A);let O=await r_(),w=O[Y.name];if(w){let j=u18(w.installLocation);if(j)throw Error(`Marketplace '${Y.name}' is seed-managed (${j}). To use a different source, ask your admin to update the seed, or use a different marketplace name.`);if(N(`Marketplace '${Y.name}' exists with different source — overwriting`),!SB(w.source)){let H=Kd(sK6()),J=Kd(w.installLocation),M=Kd($);if(J===M);else if(J===H||J.startsWith(H+fB8))await X8().rm(w.installLocation,{recursive:!0,force:!0});else N(`Skipping cleanup of old installLocation (${w.installLocation}) — `+`outside ${H}. The path is corrupted; leaving it alone and overwriting the config entry.`,{level:"warn"})}}return O[Y.name]={source:_,installLocation:$,lastUpdated:new Date().toISOString()},await _d(O),N(`Added marketplace source: ${Y.name}`),{name:Y.name,alreadyMaterialized:!1,resolvedSource:_}}async function Mh6(q){let K=await r_();if(!K[q])throw Error(`Marketplace '${q}' not found`);let _=K[q],z=u18(_.installLocation);if(z)throw Error(`Marketplace '${q}' is registered from the read-only seed directory (${z}) and will be re-registered on next startup. To stop using its plugins: claude plugin disable <plugin>@${q}`);delete K[q],await _d(K);let Y=X8(),$=sK6(),A=dX($,q);await Y.rm(A,{recursive:!0,force:!0});let O=dX($,`${q}.json`);await Y.rm(O,{force:!0});let w=["userSettings","projectSettings","localSettings"];for(let J of w){let M=v1(J);if(!M)continue;let X=!1,P={};if(M.extraKnownMarketplaces?.[q]){let W={...M.extraKnownMarketplaces};W[q]=void 0,P.extraKnownMarketplaces=W,X=!0}if(M.enabledPlugins){let W=`@${q}`,D={...M.enabledPlugins},f=!1;for(let G in D)if(G.endsWith(W))D[G]=void 0,f=!0;if(f)P.enabledPlugins=D,X=!0}if(X){let W=W7(J,P);if(W.error)H6(W.error),N(`Failed to clean up marketplace '${q}' from ${J} settings: ${W.error.message}`);else N(`Cleaned up marketplace '${q}' from ${J} settings`)}}let{orphanedPaths:j,removedPluginIds:H}=_0K(q);for(let J of j)await wh6(J);for(let J of H)Ak8(J),await WT8(J);N(`Removed marketplace source: ${q}`)}async function x18(q){let K=dX(q,".claude-plugin","marketplace.json");try{return await m17(K,de())}catch(_){if(_ instanceof hT)throw _;let z=s1(_);if(z!=="ENOENT"&&z!=="ENOTDIR")throw _}return await m17(q,de())}async function m18(q){let K=X8(),_=ZB8();try{let z=await K.readFile(_,{encoding:"utf-8"}),$=r8(z)[q];if(!$)return null;return await x18($.installLocation)}catch(z){if(_7(z))return null;return N(`Failed to read cached marketplace ${q}: ${d6(z)}`,{level:"warn"}),null}}async function B17(q){let{name:K,marketplace:_}=Z4(q);if(!K||!_)return null;let z=X8(),Y=ZB8();try{let $=await z.readFile(Y,{encoding:"utf-8"}),O=r8($)[_];if(!O)return null;let w=await m18(_);if(!w)return null;let j=w.plugins.find((H)=>H.name===K);if(!j)return null;return{entry:j,marketplaceInstallLocation:O.installLocation}}catch{return null}}async function aG(q){let K=await B17(q);if(K)return K;let{name:_,marketplace:z}=Z4(q);if(!_||!z)return null;try{let $=(await r_())[z];if(!$)return null;let O=(await r0(z)).plugins.find((w)=>w.name===_);if(!O)return null;return{entry:O,marketplaceInstallLocation:$.installLocation}}catch(Y){return N(`Could not find plugin ${q}: ${d6(Y)}`,{level:"debug"}),null}}async function q0K(){let q=await r_();for(let[K,_]of Object.entries(q)){if(u18(_.installLocation)){N(`Skipping seed-managed marketplace '${K}' in bulk refresh`);continue}if(_.source.source==="settings")continue;if(K===C2){if(await C18(_.installLocation,sK6())!==null){q[K].lastUpdated=new Date().toISOString();continue}if(!g8("tengu_plugin_official_mkt_git_fallback",!0)){N("Skipping official marketplace bulk refresh: GCS failed, git fallback disabled");continue}}try{let{cachePath:z}=await p17(_.source);q[K].lastUpdated=new Date().toISOString(),q[K].installLocation=z}catch(z){N(`Failed to refresh marketplace ${K}: ${d6(z)}`,{level:"error"})}}await _d(q)}async function q56(q,K,_){let z=await r_(),Y=z[q];if(!Y)throw Error(`Marketplace '${q}' not found. Available marketplaces: ${Object.keys(z).join(", ")}`);if(r0.cache?.delete?.(q),Y.source.source==="settings"){N(`Skipping refresh for settings-sourced marketplace '${q}' — no upstream`);return}try{let{installLocation:$,source:A}=Y,O=u18($);if(O)throw Error(`Marketplace '${q}' is seed-managed (${O}) and its content is controlled by the seed image. To update: ask your admin to update the seed.`);if(!SB(A)){let w=Kd(sK6()),j=Kd($);if(j!==w&&!j.startsWith(w+fB8))throw Error(`Marketplace '${q}' has a corrupted installLocation (${$}) — expected a path inside ${w}. This can happen after cross-platform path writes or manual edits to known_marketplaces.json. Run: claude plugin marketplace remove "${q}" and re-add it.`)}if(q===C2){if(await C18($,sK6())!==null){z[q]={...Y,lastUpdated:new Date().toISOString()},await _d(z);return}if(!g8("tengu_plugin_official_mkt_git_fallback",!0))throw Error("Official marketplace GCS fetch failed and git fallback is disabled");N("Official marketplace GCS failed; falling back to git",{level:"warn"})}if(A.source==="github"||A.source==="git"){if(A.source==="github"){let w=`git@github.com:${A.repo}.git`,j=`https://github.com/${A.repo}.git`;if(i6(process.env.CLAUDE_CODE_REMOTE))await Ba(j,$,A.ref,A.sparsePaths,K,_);else{let H=await tfK(),J=H?w:j,M=H?j:w;try{await Ba(J,$,A.ref,A.sparsePaths,K,_)}catch{N(`Marketplace refresh failed with ${H?"SSH":"HTTPS"} for ${A.repo}, falling back to ${H?"HTTPS":"SSH"}`,{level:"info"}),await Ba(M,$,A.ref,A.sparsePaths,K,_)}}}else await Ba(A.url,$,A.ref,A.sparsePaths,K,_);try{await x18($)}catch{let w=A.source==="github"?A.repo:EH6(A.url);throw Error(`The marketplace.json file is no longer present in this repository. |
| 4718 | |
| 4719 | ${q==="claude-code-plugins"?`We've deprecated "claude-code-plugins" in favor of "claude-plugins-official".`:"This marketplace may have been deprecated or moved to a new location."} |