@leviyuan/lodestar 0.12.1 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -140,7 +140,7 @@ curl -sS -X POST http://127.0.0.1:9876/notify \
140
140
 
141
141
  ### 想让某个外部项目跑在别的目录?
142
142
 
143
- 默认群名就是 `projects_root` 下的目录名。但如果你的项目放在别处、不想搬进来,在 config.toml 指一下它的目录就行,其它项目不受影响:
143
+ 默认群名就是 `projects_root` 下的目录名。但如果你的项目放在别处、不想搬进来,在 config.toml 指一下它的目录就行——**section 名就是飞书群名**(daemon 用群名去 `config.projects[群名]` 取 cwd),其它项目不受影响:
144
144
 
145
145
  ```toml
146
146
  [projects.calculator2]
@@ -155,10 +155,11 @@ cwd = "/abs/path/to/calculator2"
155
155
  setting_sources = "project" # 只读项目级配置(会丢全局)
156
156
  strict_mcp = "true" # 只挂项目 .mcp.json,挡掉全局 MCP
157
157
  tools = "Read,Write,Edit,Bash,Glob,Grep"
158
- load_project_mcp = "true" # 读 <cwd>/.mcp.json
159
158
  ```
160
159
 
161
- > 最常踩的坑:`setting_sources = "project"` 会把 `~/.claude/settings.json` 里的 GLM 路由一起丢掉 —— 走 project 模式时,GLM 路由得改落在 config.toml 的 `[claude.env]` 里。要是看到卡片一直 `Thinking...`、model 显示 `<synthetic>`,先把整节注释掉重启,基本就是这几个开关没配齐。
160
+ > `<cwd>/.mcp.json` 默认就会被读(对齐裸 `claude` 的项目 MCP 自动发现),不用单独开;只有想关掉才设 `load_project_mcp = "false"`。
161
+ >
162
+ > 最常踩的坑:`setting_sources = "project"` 会把 `~/.claude/settings.json` 里的 GLM 路由一起丢掉 —— `[claude.env]` 是**无差别注入到所有项目** spawn env 的(不只对这一个项目生效),把 GLM 的 base_url / token 挪过去就能兜住。要是看到卡片一直 `Thinking...`、model 显示 `<synthetic>`,先把整节注释掉重启,基本就是这几个开关没配齐。
162
163
 
163
164
  ### 想换成 reclaude 之类的 claude 包装器?
164
165
 
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{spawn as b}from"node:child_process";import{existsSync as g}from"node:fs";import{homedir as d}from"node:os";import{join as o}from"node:path";var r=d(),a=process.platform==="win32";function $(e,l,m){if(e)return e;if(l)return o(l,"lodestar");return m}function y(){if(a)return o(process.env.APPDATA??o(r,"AppData","Roaming"),"Lodestar");return o(r,".config","lodestar")}function C(){if(a)return o(process.env.LOCALAPPDATA??o(r,"AppData","Local"),"Lodestar");return o(r,".local","share","lodestar")}var u=$(process.env.LODESTAR_CONFIG_DIR,process.env.XDG_CONFIG_HOME,y()),t=$(process.env.LODESTAR_DATA_DIR,process.env.XDG_DATA_HOME,C()),K=process.env.LODESTAR_CONFIG??o(u,"config.toml"),n=o(t,"daemon.pid"),f=o(t,"daemon.log"),S=o(t,"session-chat-map.json"),q=o(t,"session-resume-map.json"),z=o(t,"session-turns-map.json"),J=o(t,"session-model-map.json"),Q=o(t,"tasklist-map.json"),Y=o(t,"notify-callbacks.json"),Z=o(t,"alive-on-shutdown.json"),i=o(t,"inbox"),W=o(t,"debug.sock"),X=o(t,"debug-context.json");var s={reset:"\x1B[0m",bold:"\x1B[1m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",red:"\x1B[31m",dim:"\x1B[2m"},p=["@leviyuan/lodestar@latest","@openai/codex@latest","@anthropic-ai/claude-code@latest","@anthropic-ai/claude-agent-sdk@latest","@anthropic-ai/sdk@latest"];function w(){let e=process.platform==="win32"?"npm.cmd":"npm";return new Promise((l)=>{let m=b(e,["install","-g",...p],{stdio:"inherit",shell:process.platform==="win32"});m.on("exit",(c)=>l(c??1)),m.on("error",(c)=>{console.error(`${s.red}spawn npm 失败:${s.reset} ${c.message}`),l(1)})})}async function x(){console.log(`${s.bold}更新 Lodestar + Codex CLI + Claude Code / SDK${s.reset}`),console.log(`${s.dim}npm i -g ${p.join(" ")}${s.reset}
2
+ import{spawn as b}from"node:child_process";import{existsSync as g}from"node:fs";import{homedir as d}from"node:os";import{join as o}from"node:path";var r=d(),a=process.platform==="win32";function n(e,l,m){if(e)return e;if(l)return o(l,"lodestar");return m}function y(){if(a)return o(process.env.APPDATA??o(r,"AppData","Roaming"),"Lodestar");return o(r,".config","lodestar")}function u(){if(a)return o(process.env.LOCALAPPDATA??o(r,"AppData","Local"),"Lodestar");return o(r,".local","share","lodestar")}var C=n(process.env.LODESTAR_CONFIG_DIR,process.env.XDG_CONFIG_HOME,y()),t=n(process.env.LODESTAR_DATA_DIR,process.env.XDG_DATA_HOME,u()),K=process.env.LODESTAR_CONFIG??o(C,"config.toml"),$=o(t,"daemon.pid"),f=o(t,"daemon.log"),S=o(t,"session-chat-map.json"),i=o(t,"session-resume-map.json"),q=o(t,"session-turns-map.json"),z=o(t,"session-model-map.json"),J=o(t,"tasklist-map.json"),Q=o(t,"notify-callbacks.json"),Y=o(t,"alive-on-shutdown.json"),Z=o(t,"inbox"),W=o(t,"debug.sock"),X=o(t,"debug-context.json");var s={reset:"\x1B[0m",bold:"\x1B[1m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",red:"\x1B[31m",dim:"\x1B[2m"},p=["@leviyuan/lodestar@latest","@openai/codex@latest","@anthropic-ai/claude-code@latest","@anthropic-ai/claude-agent-sdk@latest","@anthropic-ai/sdk@latest"];function w(){let e=process.platform==="win32"?"npm.cmd":"npm";return new Promise((l)=>{let m=b(e,["install","-g","--include=optional",...p],{stdio:"inherit",shell:process.platform==="win32"});m.on("exit",(c)=>l(c??1)),m.on("error",(c)=>{console.error(`${s.red}spawn npm 失败:${s.reset} ${c.message}`),l(1)})})}async function x(){console.log(`${s.bold}更新 Lodestar + Codex CLI + Claude Code / SDK${s.reset}`),console.log(`${s.dim}npm i -g ${p.join(" ")}${s.reset}
3
3
  `);let e=await w();if(e!==0)console.error(`
4
4
  ${s.red}更新失败 (npm exit ${e})${s.reset}`),process.exit(e);if(console.log(`
5
- ${s.green}✓ 更新完成${s.reset}`),g(n))console.log(),console.log(`${s.yellow}检测到 daemon 仍在跑老版本进程, 用新版本需要重启:${s.reset}`),console.log(` ${s.dim}# systemd / Windows 后台托管的:${s.reset}`),console.log(` ${s.cyan}systemctl --user restart lodestar${s.reset} ${s.dim}# Linux/macOS${s.reset}`),console.log(` ${s.dim}# 或手动重启:${s.reset}`),console.log(` ${s.cyan}lodestar-stop && lodestar-daemon${s.reset}`)}x().catch((e)=>{console.error(`${s.red}lodestar-update:${s.reset} ${e?.message??e}`),process.exit(1)});
5
+ ${s.green}✓ 更新完成${s.reset}`),g($))console.log(),console.log(`${s.yellow}检测到 daemon 仍在跑老版本进程, 用新版本需要重启:${s.reset}`),console.log(` ${s.dim}# systemd / Windows 后台托管的:${s.reset}`),console.log(` ${s.cyan}systemctl --user restart lodestar${s.reset} ${s.dim}# Linux/macOS${s.reset}`),console.log(` ${s.dim}# 或手动重启:${s.reset}`),console.log(` ${s.cyan}lodestar-stop && lodestar-daemon${s.reset}`)}x().catch((e)=>{console.error(`${s.red}lodestar-update:${s.reset} ${e?.message??e}`),process.exit(1)});
package/dist/lodestar.js CHANGED
@@ -218,7 +218,7 @@ Please migrate to a newer model. Visit https://docs.anthropic.com/en/docs/resour
218
218
  `+" ".repeat(Z))},"\t":{"\n":Array(200).fill(0).map((x,Z)=>`
219
219
  `+"\t".repeat(Z)),"\r":Array(200).fill(0).map((x,Z)=>"\r"+"\t".repeat(Z)),"\r\n":Array(200).fill(0).map((x,Z)=>`\r
220
220
  `+"\t".repeat(Z))}};(function(x){x.DEFAULT={allowTrailingComma:!1}})(Ac||(Ac={}));(function(x){x[x.None=0]="None",x[x.UnexpectedEndOfComment=1]="UnexpectedEndOfComment",x[x.UnexpectedEndOfString=2]="UnexpectedEndOfString",x[x.UnexpectedEndOfNumber=3]="UnexpectedEndOfNumber",x[x.InvalidUnicode=4]="InvalidUnicode",x[x.InvalidEscapeCharacter=5]="InvalidEscapeCharacter",x[x.InvalidCharacter=6]="InvalidCharacter"})(Ec||(Ec={}));(function(x){x[x.OpenBraceToken=1]="OpenBraceToken",x[x.CloseBraceToken=2]="CloseBraceToken",x[x.OpenBracketToken=3]="OpenBracketToken",x[x.CloseBracketToken=4]="CloseBracketToken",x[x.CommaToken=5]="CommaToken",x[x.ColonToken=6]="ColonToken",x[x.NullKeyword=7]="NullKeyword",x[x.TrueKeyword=8]="TrueKeyword",x[x.FalseKeyword=9]="FalseKeyword",x[x.StringLiteral=10]="StringLiteral",x[x.NumericLiteral=11]="NumericLiteral",x[x.LineCommentTrivia=12]="LineCommentTrivia",x[x.BlockCommentTrivia=13]="BlockCommentTrivia",x[x.LineBreakTrivia=14]="LineBreakTrivia",x[x.Trivia=15]="Trivia",x[x.Unknown=16]="Unknown",x[x.EOF=17]="EOF"})(bc||(bc={}));(function(x){x[x.InvalidSymbol=1]="InvalidSymbol",x[x.InvalidNumberFormat=2]="InvalidNumberFormat",x[x.PropertyNameExpected=3]="PropertyNameExpected",x[x.ValueExpected=4]="ValueExpected",x[x.ColonExpected=5]="ColonExpected",x[x.CommaExpected=6]="CommaExpected",x[x.CloseBraceExpected=7]="CloseBraceExpected",x[x.CloseBracketExpected=8]="CloseBracketExpected",x[x.EndOfFileExpected=9]="EndOfFileExpected",x[x.InvalidCommentToken=10]="InvalidCommentToken",x[x.UnexpectedEndOfComment=11]="UnexpectedEndOfComment",x[x.UnexpectedEndOfString=12]="UnexpectedEndOfString",x[x.UnexpectedEndOfNumber=13]="UnexpectedEndOfNumber",x[x.InvalidUnicode=14]="InvalidUnicode",x[x.InvalidEscapeCharacter=15]="InvalidEscapeCharacter",x[x.InvalidCharacter=16]="InvalidCharacter"})(kc||(kc={}));U6=$P.homedir(),zU=$P.tmpdir(),{env:l7}=eH;RR0=MK0("claude-cli");IH=[];TK0=[],SR0=Q1(()=>process.argv.includes("--hard-fail"));y7=typeof performance==="object"&&performance&&typeof performance.now==="function"?performance:Date,UP=new Set,aH=typeof process==="object"&&!!process?process:{},yJ=globalThis.AbortController,Pc=globalThis.AbortSignal;if(typeof yJ>"u"){Pc=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(Q,J){this._onabort.push(J)}},yJ=class{constructor(){Z()}signal=new Pc;abort(Q){if(this.signal.aborted)return;this.signal.reason=Q,this.signal.aborted=!0;for(let J of this.signal._onabort)J(Q);this.signal.onabort?.(Q)}};let x=aH.env?.LRU_CACHE_IGNORE_AC_WARNING!=="1",Z=()=>{if(!x)return;x=!1,NP("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",Z)}}CR0=Symbol("type");R2=class R2 extends Array{constructor(x){super(x);this.fill(0)}};WU=class WU{#Q;#G;#N;#L;#A;#E;ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#X;#D;#J;#Z;#x;#V;#$;#K;#z;#O;#W;#B;#v;#F;#M;#T;#H;static unsafeExposeInternals(x){return{starts:x.#v,ttls:x.#F,sizes:x.#B,keyMap:x.#J,keyList:x.#Z,valList:x.#x,next:x.#V,prev:x.#$,get head(){return x.#K},get tail(){return x.#z},free:x.#O,isBackgroundFetch:(Z)=>x.#Y(Z),backgroundFetch:(Z,Q,J,X)=>x.#g(Z,Q,J,X),moveToTail:(Z)=>x.#q(Z),indexes:(Z)=>x.#R(Z),rindexes:(Z)=>x.#S(Z),isStale:(Z)=>x.#U(Z)}}get max(){return this.#Q}get maxSize(){return this.#G}get calculatedSize(){return this.#D}get size(){return this.#X}get fetchMethod(){return this.#A}get memoMethod(){return this.#E}get dispose(){return this.#N}get disposeAfter(){return this.#L}constructor(x){let{max:Z=0,ttl:Q,ttlResolution:J=1,ttlAutopurge:X,updateAgeOnGet:z,updateAgeOnHas:Y,allowStale:G,dispose:K,disposeAfter:H,noDisposeOnSet:W,noUpdateTTL:N,maxSize:L=0,maxEntrySize:D=0,sizeCalculation:O,fetchMethod:v,memoMethod:B,noDeleteOnFetchRejection:j,noDeleteOnStaleGet:c,allowStaleOnFetchRejection:T,allowStaleOnFetchAbort:k,ignoreFetchAbort:w}=x;if(Z!==0&&!G6(Z))throw TypeError("max option must be a nonnegative integer");let P=Z?LP(Z):Array;if(!P)throw Error("invalid max value: "+Z);if(this.#Q=Z,this.#G=L,this.maxEntrySize=D||this.#G,this.sizeCalculation=O,this.sizeCalculation){if(!this.#G&&!this.maxEntrySize)throw TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!=="function")throw TypeError("sizeCalculation set to non-function")}if(B!==void 0&&typeof B!=="function")throw TypeError("memoMethod must be a function if defined");if(this.#E=B,v!==void 0&&typeof v!=="function")throw TypeError("fetchMethod must be a function if specified");if(this.#A=v,this.#T=!!v,this.#J=new Map,this.#Z=Array(Z).fill(void 0),this.#x=Array(Z).fill(void 0),this.#V=new P(Z),this.#$=new P(Z),this.#K=0,this.#z=0,this.#O=d7.create(Z),this.#X=0,this.#D=0,typeof K==="function")this.#N=K;if(typeof H==="function")this.#L=H,this.#W=[];else this.#L=void 0,this.#W=void 0;if(this.#M=!!this.#N,this.#H=!!this.#L,this.noDisposeOnSet=!!W,this.noUpdateTTL=!!N,this.noDeleteOnFetchRejection=!!j,this.allowStaleOnFetchRejection=!!T,this.allowStaleOnFetchAbort=!!k,this.ignoreFetchAbort=!!w,this.maxEntrySize!==0){if(this.#G!==0){if(!G6(this.#G))throw TypeError("maxSize must be a positive integer if specified")}if(!G6(this.maxEntrySize))throw TypeError("maxEntrySize must be a positive integer if specified");this.#m()}if(this.allowStale=!!G,this.noDeleteOnStaleGet=!!c,this.updateAgeOnGet=!!z,this.updateAgeOnHas=!!Y,this.ttlResolution=G6(J)||J===0?J:1,this.ttlAutopurge=!!X,this.ttl=Q||0,this.ttl){if(!G6(this.ttl))throw TypeError("ttl must be a positive integer if specified");this.#P()}if(this.#Q===0&&this.ttl===0&&this.#G===0)throw TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#Q&&!this.#G){if(IK0("LRU_CACHE_UNBOUNDED"))UP.add("LRU_CACHE_UNBOUNDED"),NP("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning","LRU_CACHE_UNBOUNDED",WU)}}getRemainingTTL(x){return this.#J.has(x)?1/0:0}#P(){let x=new R2(this.#Q),Z=new R2(this.#Q);this.#F=x,this.#v=Z,this.#w=(X,z,Y=y7.now())=>{if(Z[X]=z!==0?Y:0,x[X]=z,z!==0&&this.ttlAutopurge){let G=setTimeout(()=>{if(this.#U(X))this.#C(this.#Z[X],"expire")},z+1);if(G.unref)G.unref()}},this.#I=(X)=>{Z[X]=x[X]!==0?y7.now():0},this.#j=(X,z)=>{if(x[z]){let Y=x[z],G=Z[z];if(!Y||!G)return;X.ttl=Y,X.start=G,X.now=Q||J();let K=X.now-G;X.remainingTTL=Y-K}};let Q=0,J=()=>{let X=y7.now();if(this.ttlResolution>0){Q=X;let z=setTimeout(()=>Q=0,this.ttlResolution);if(z.unref)z.unref()}return X};this.getRemainingTTL=(X)=>{let z=this.#J.get(X);if(z===void 0)return 0;let Y=x[z],G=Z[z];if(!Y||!G)return 1/0;let K=(Q||J())-G;return Y-K},this.#U=(X)=>{let z=Z[X],Y=x[X];return!!Y&&!!z&&(Q||J())-z>Y}}#I=()=>{};#j=()=>{};#w=()=>{};#U=()=>!1;#m(){let x=new R2(this.#Q);this.#D=0,this.#B=x,this.#c=(Z)=>{this.#D-=x[Z],x[Z]=0},this.#u=(Z,Q,J,X)=>{if(this.#Y(Q))return 0;if(!G6(J))if(X){if(typeof X!=="function")throw TypeError("sizeCalculation must be a function");if(J=X(Q,Z),!G6(J))throw TypeError("sizeCalculation return invalid (expect positive integer)")}else throw TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");return J},this.#b=(Z,Q,J)=>{if(x[Z]=Q,this.#G){let X=this.#G-x[Z];while(this.#D>X)this.#k(!0)}if(this.#D+=x[Z],J)J.entrySize=Q,J.totalCalculatedSize=this.#D}}#c=(x)=>{};#b=(x,Z,Q)=>{};#u=(x,Z,Q,J)=>{if(Q||J)throw TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#R({allowStale:x=this.allowStale}={}){if(this.#X)for(let Z=this.#z;;){if(!this.#f(Z))break;if(x||!this.#U(Z))yield Z;if(Z===this.#K)break;else Z=this.#$[Z]}}*#S({allowStale:x=this.allowStale}={}){if(this.#X)for(let Z=this.#K;;){if(!this.#f(Z))break;if(x||!this.#U(Z))yield Z;if(Z===this.#z)break;else Z=this.#V[Z]}}#f(x){return x!==void 0&&this.#J.get(this.#Z[x])===x}*entries(){for(let x of this.#R())if(this.#x[x]!==void 0&&this.#Z[x]!==void 0&&!this.#Y(this.#x[x]))yield[this.#Z[x],this.#x[x]]}*rentries(){for(let x of this.#S())if(this.#x[x]!==void 0&&this.#Z[x]!==void 0&&!this.#Y(this.#x[x]))yield[this.#Z[x],this.#x[x]]}*keys(){for(let x of this.#R()){let Z=this.#Z[x];if(Z!==void 0&&!this.#Y(this.#x[x]))yield Z}}*rkeys(){for(let x of this.#S()){let Z=this.#Z[x];if(Z!==void 0&&!this.#Y(this.#x[x]))yield Z}}*values(){for(let x of this.#R())if(this.#x[x]!==void 0&&!this.#Y(this.#x[x]))yield this.#x[x]}*rvalues(){for(let x of this.#S())if(this.#x[x]!==void 0&&!this.#Y(this.#x[x]))yield this.#x[x]}[Symbol.iterator](){return this.entries()}[Symbol.toStringTag]="LRUCache";find(x,Z={}){for(let Q of this.#R()){let J=this.#x[Q],X=this.#Y(J)?J.__staleWhileFetching:J;if(X===void 0)continue;if(x(X,this.#Z[Q],this))return this.get(this.#Z[Q],Z)}}forEach(x,Z=this){for(let Q of this.#R()){let J=this.#x[Q],X=this.#Y(J)?J.__staleWhileFetching:J;if(X===void 0)continue;x.call(Z,X,this.#Z[Q],this)}}rforEach(x,Z=this){for(let Q of this.#S()){let J=this.#x[Q],X=this.#Y(J)?J.__staleWhileFetching:J;if(X===void 0)continue;x.call(Z,X,this.#Z[Q],this)}}purgeStale(){let x=!1;for(let Z of this.#S({allowStale:!0}))if(this.#U(Z))this.#C(this.#Z[Z],"expire"),x=!0;return x}info(x){let Z=this.#J.get(x);if(Z===void 0)return;let Q=this.#x[Z],J=this.#Y(Q)?Q.__staleWhileFetching:Q;if(J===void 0)return;let X={value:J};if(this.#F&&this.#v){let z=this.#F[Z],Y=this.#v[Z];if(z&&Y){let G=z-(y7.now()-Y);X.ttl=G,X.start=Date.now()}}if(this.#B)X.size=this.#B[Z];return X}dump(){let x=[];for(let Z of this.#R({allowStale:!0})){let Q=this.#Z[Z],J=this.#x[Z],X=this.#Y(J)?J.__staleWhileFetching:J;if(X===void 0||Q===void 0)continue;let z={value:X};if(this.#F&&this.#v){z.ttl=this.#F[Z];let Y=y7.now()-this.#v[Z];z.start=Math.floor(Date.now()-Y)}if(this.#B)z.size=this.#B[Z];x.unshift([Q,z])}return x}load(x){this.clear();for(let[Z,Q]of x){if(Q.start){let J=Date.now()-Q.start;Q.start=y7.now()-J}this.set(Z,Q.value,Q)}}set(x,Z,Q={}){if(Z===void 0)return this.delete(x),this;let{ttl:J=this.ttl,start:X,noDisposeOnSet:z=this.noDisposeOnSet,sizeCalculation:Y=this.sizeCalculation,status:G}=Q,{noUpdateTTL:K=this.noUpdateTTL}=Q,H=this.#u(x,Z,Q.size||0,Y);if(this.maxEntrySize&&H>this.maxEntrySize){if(G)G.set="miss",G.maxEntrySizeExceeded=!0;return this.#C(x,"set"),this}let W=this.#X===0?void 0:this.#J.get(x);if(W===void 0){if(W=this.#X===0?this.#z:this.#O.length!==0?this.#O.pop():this.#X===this.#Q?this.#k(!1):this.#X,this.#Z[W]=x,this.#x[W]=Z,this.#J.set(x,W),this.#V[this.#z]=W,this.#$[W]=this.#z,this.#z=W,this.#X++,this.#b(W,H,G),G)G.set="add";K=!1}else{this.#q(W);let N=this.#x[W];if(Z!==N){if(this.#T&&this.#Y(N)){N.__abortController.abort(Error("replaced"));let{__staleWhileFetching:L}=N;if(L!==void 0&&!z){if(this.#M)this.#N?.(L,x,"set");if(this.#H)this.#W?.push([L,x,"set"])}}else if(!z){if(this.#M)this.#N?.(N,x,"set");if(this.#H)this.#W?.push([N,x,"set"])}if(this.#c(W),this.#b(W,H,G),this.#x[W]=Z,G){G.set="replace";let L=N&&this.#Y(N)?N.__staleWhileFetching:N;if(L!==void 0)G.oldValue=L}}else if(G)G.set="update"}if(J!==0&&!this.#F)this.#P();if(this.#F){if(!K)this.#w(W,J,X);if(G)this.#j(G,W)}if(!z&&this.#H&&this.#W){let N=this.#W,L;while(L=N?.shift())this.#L?.(...L)}return this}pop(){try{while(this.#X){let x=this.#x[this.#K];if(this.#k(!0),this.#Y(x)){if(x.__staleWhileFetching)return x.__staleWhileFetching}else if(x!==void 0)return x}}finally{if(this.#H&&this.#W){let x=this.#W,Z;while(Z=x?.shift())this.#L?.(...Z)}}}#k(x){let Z=this.#K,Q=this.#Z[Z],J=this.#x[Z];if(this.#T&&this.#Y(J))J.__abortController.abort(Error("evicted"));else if(this.#M||this.#H){if(this.#M)this.#N?.(J,Q,"evict");if(this.#H)this.#W?.push([J,Q,"evict"])}if(this.#c(Z),x)this.#Z[Z]=void 0,this.#x[Z]=void 0,this.#O.push(Z);if(this.#X===1)this.#K=this.#z=0,this.#O.length=0;else this.#K=this.#V[Z];return this.#J.delete(Q),this.#X--,Z}has(x,Z={}){let{updateAgeOnHas:Q=this.updateAgeOnHas,status:J}=Z,X=this.#J.get(x);if(X!==void 0){let z=this.#x[X];if(this.#Y(z)&&z.__staleWhileFetching===void 0)return!1;if(!this.#U(X)){if(Q)this.#I(X);if(J)J.has="hit",this.#j(J,X);return!0}else if(J)J.has="stale",this.#j(J,X)}else if(J)J.has="miss";return!1}peek(x,Z={}){let{allowStale:Q=this.allowStale}=Z,J=this.#J.get(x);if(J===void 0||!Q&&this.#U(J))return;let X=this.#x[J];return this.#Y(X)?X.__staleWhileFetching:X}#g(x,Z,Q,J){let X=Z===void 0?void 0:this.#x[Z];if(this.#Y(X))return X;let z=new yJ,{signal:Y}=Q;Y?.addEventListener("abort",()=>z.abort(Y.reason),{signal:z.signal});let G={signal:z.signal,options:Q,context:J},K=(O,v=!1)=>{let{aborted:B}=z.signal,j=Q.ignoreFetchAbort&&O!==void 0;if(Q.status)if(B&&!v){if(Q.status.fetchAborted=!0,Q.status.fetchError=z.signal.reason,j)Q.status.fetchAbortIgnored=!0}else Q.status.fetchResolved=!0;if(B&&!j&&!v)return W(z.signal.reason);let c=L;if(this.#x[Z]===L)if(O===void 0)if(c.__staleWhileFetching)this.#x[Z]=c.__staleWhileFetching;else this.#C(x,"fetch");else{if(Q.status)Q.status.fetchUpdated=!0;this.set(x,O,G.options)}return O},H=(O)=>{if(Q.status)Q.status.fetchRejected=!0,Q.status.fetchError=O;return W(O)},W=(O)=>{let{aborted:v}=z.signal,B=v&&Q.allowStaleOnFetchAbort,j=B||Q.allowStaleOnFetchRejection,c=j||Q.noDeleteOnFetchRejection,T=L;if(this.#x[Z]===L){if(!c||T.__staleWhileFetching===void 0)this.#C(x,"fetch");else if(!B)this.#x[Z]=T.__staleWhileFetching}if(j){if(Q.status&&T.__staleWhileFetching!==void 0)Q.status.returnedStale=!0;return T.__staleWhileFetching}else if(T.__returned===T)throw O},N=(O,v)=>{let B=this.#A?.(x,X,G);if(B&&B instanceof Promise)B.then((j)=>O(j===void 0?void 0:j),v);z.signal.addEventListener("abort",()=>{if(!Q.ignoreFetchAbort||Q.allowStaleOnFetchAbort){if(O(void 0),Q.allowStaleOnFetchAbort)O=(j)=>K(j,!0)}})};if(Q.status)Q.status.fetchDispatched=!0;let L=new Promise(N).then(K,H),D=Object.assign(L,{__abortController:z,__staleWhileFetching:X,__returned:void 0});if(Z===void 0)this.set(x,D,{...G.options,status:void 0}),Z=this.#J.get(x);else this.#x[Z]=D;return D}#Y(x){if(!this.#T)return!1;let Z=x;return!!Z&&Z instanceof Promise&&Z.hasOwnProperty("__staleWhileFetching")&&Z.__abortController instanceof yJ}async fetch(x,Z={}){let{allowStale:Q=this.allowStale,updateAgeOnGet:J=this.updateAgeOnGet,noDeleteOnStaleGet:X=this.noDeleteOnStaleGet,ttl:z=this.ttl,noDisposeOnSet:Y=this.noDisposeOnSet,size:G=0,sizeCalculation:K=this.sizeCalculation,noUpdateTTL:H=this.noUpdateTTL,noDeleteOnFetchRejection:W=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:N=this.allowStaleOnFetchRejection,ignoreFetchAbort:L=this.ignoreFetchAbort,allowStaleOnFetchAbort:D=this.allowStaleOnFetchAbort,context:O,forceRefresh:v=!1,status:B,signal:j}=Z;if(!this.#T){if(B)B.fetch="get";return this.get(x,{allowStale:Q,updateAgeOnGet:J,noDeleteOnStaleGet:X,status:B})}let c={allowStale:Q,updateAgeOnGet:J,noDeleteOnStaleGet:X,ttl:z,noDisposeOnSet:Y,size:G,sizeCalculation:K,noUpdateTTL:H,noDeleteOnFetchRejection:W,allowStaleOnFetchRejection:N,allowStaleOnFetchAbort:D,ignoreFetchAbort:L,status:B,signal:j},T=this.#J.get(x);if(T===void 0){if(B)B.fetch="miss";let k=this.#g(x,T,c,O);return k.__returned=k}else{let k=this.#x[T];if(this.#Y(k)){let q=Q&&k.__staleWhileFetching!==void 0;if(B){if(B.fetch="inflight",q)B.returnedStale=!0}return q?k.__staleWhileFetching:k.__returned=k}let w=this.#U(T);if(!v&&!w){if(B)B.fetch="hit";if(this.#q(T),J)this.#I(T);if(B)this.#j(B,T);return k}let P=this.#g(x,T,c,O),I=P.__staleWhileFetching!==void 0&&Q;if(B){if(B.fetch=w?"stale":"refresh",I&&w)B.returnedStale=!0}return I?P.__staleWhileFetching:P.__returned=P}}async forceFetch(x,Z={}){let Q=await this.fetch(x,Z);if(Q===void 0)throw Error("fetch() returned undefined");return Q}memo(x,Z={}){let Q=this.#E;if(!Q)throw Error("no memoMethod provided to constructor");let{context:J,forceRefresh:X,...z}=Z,Y=this.get(x,z);if(!X&&Y!==void 0)return Y;let G=Q(x,Y,{options:z,context:J});return this.set(x,G,z),G}get(x,Z={}){let{allowStale:Q=this.allowStale,updateAgeOnGet:J=this.updateAgeOnGet,noDeleteOnStaleGet:X=this.noDeleteOnStaleGet,status:z}=Z,Y=this.#J.get(x);if(Y!==void 0){let G=this.#x[Y],K=this.#Y(G);if(z)this.#j(z,Y);if(this.#U(Y)){if(z)z.get="stale";if(!K){if(!X)this.#C(x,"expire");if(z&&Q)z.returnedStale=!0;return Q?G:void 0}else{if(z&&Q&&G.__staleWhileFetching!==void 0)z.returnedStale=!0;return Q?G.__staleWhileFetching:void 0}}else{if(z)z.get="hit";if(K)return G.__staleWhileFetching;if(this.#q(Y),J)this.#I(Y);return G}}else if(z)z.get="miss"}#y(x,Z){this.#$[Z]=x,this.#V[x]=Z}#q(x){if(x!==this.#z){if(x===this.#K)this.#K=this.#V[x];else this.#y(this.#$[x],this.#V[x]);this.#y(this.#z,x),this.#z=x}}delete(x){return this.#C(x,"delete")}#C(x,Z){let Q=!1;if(this.#X!==0){let J=this.#J.get(x);if(J!==void 0)if(Q=!0,this.#X===1)this.#h(Z);else{this.#c(J);let X=this.#x[J];if(this.#Y(X))X.__abortController.abort(Error("deleted"));else if(this.#M||this.#H){if(this.#M)this.#N?.(X,x,Z);if(this.#H)this.#W?.push([X,x,Z])}if(this.#J.delete(x),this.#Z[J]=void 0,this.#x[J]=void 0,J===this.#z)this.#z=this.#$[J];else if(J===this.#K)this.#K=this.#V[J];else{let z=this.#$[J];this.#V[z]=this.#V[J];let Y=this.#V[J];this.#$[Y]=this.#$[J]}this.#X--,this.#O.push(J)}}if(this.#H&&this.#W?.length){let J=this.#W,X;while(X=J?.shift())this.#L?.(...X)}return Q}clear(){return this.#h("delete")}#h(x){for(let Z of this.#S({allowStale:!0})){let Q=this.#x[Z];if(this.#Y(Q))Q.__abortController.abort(Error("deleted"));else{let J=this.#Z[Z];if(this.#M)this.#N?.(Q,J,x);if(this.#H)this.#W?.push([Q,J,x])}}if(this.#J.clear(),this.#x.fill(void 0),this.#Z.fill(void 0),this.#F&&this.#v)this.#F.fill(0),this.#v.fill(0);if(this.#B)this.#B.fill(0);if(this.#K=0,this.#z=0,this.#O.length=0,this.#D=0,this.#X=0,this.#H&&this.#W){let Z=this.#W,Q;while(Q=Z?.shift())this.#L?.(...Q)}}};wc=cK0(DP,(x)=>x,50),jR0=Object.assign(function(x,Z=!0){if(!x)return null;let Q=x.length>qK0?DP(x,Z):wc(x,Z);return Q.ok?Q.value:null},{cache:wc.cache}),BP=Q1(()=>{try{if(process.platform==="darwin")return"macos";if(process.platform==="win32")return"windows";if(process.platform==="linux"){if(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP)return"wsl";try{let x=v2().readFileSync("/proc/version",{encoding:"utf8"});if(x.toLowerCase().includes("microsoft")||x.toLowerCase().includes("wsl"))return"wsl"}catch(x){Ix(`Failed to read /proc/version for WSL detection: ${x}`,{level:"error"})}return"linux"}return"unknown"}catch(x){return FP(x),"unknown"}}),AR0=Q1(()=>{if(process.platform!=="linux")return;try{let x=v2().readFileSync("/proc/version",{encoding:"utf8"}),Z=x.match(/WSL(\d+)/i);if(Z&&Z[1])return Z[1];if(x.toLowerCase().includes("microsoft"))return"1";return}catch(x){Ix(`Failed to read /proc/version for WSL detection: ${x}`,{level:"error"});return}}),ER0=Q1(async()=>{if(process.platform!=="linux")return;let x={linuxKernel:OP()};try{let Z=await EK0("/etc/os-release","utf8");for(let Q of Z.split(`
221
- `)){let J=Q.match(/^(ID|VERSION_ID)=(.*)$/);if(J&&J[1]&&J[2]){let X=J[2].replace(/^"|"$/g,"");if(J[1]==="ID")x.linuxDistroId=X;else x.linuxDistroVersion=X}}}catch{}return x}),bR0=Q1(()=>{if(process.platform!=="darwin")return;let x=OP().match(/^(\d+)\./);if(!x||!x[1])return;return parseInt(x[1],10)-9}),bK0=Q1(function(){switch(BP()){case"macos":return"/Library/Application Support/ClaudeCode";case"windows":return"C:\\Program Files\\ClaudeCode";default:return"/etc/claude-code"}}),kR0=Q1(function(){return AK0(bK0(),"managed-settings.d")});xG=kK0;PK0=gK0,wK0=PK0(),uK0=wK0;yK0=fK0,mK0=Function.prototype,_K0=Object.prototype,vP=mK0.toString,nK0=_K0.hasOwnProperty,lK0=vP.call(Object);iK0=dK0;YG=pK0;oK0=sK0;tK0=rK0;eK0=MP;xV0=aK0,uc=Math.max;RP=YV0;QV0=ZV0,JV0=!DJ?OA:function(x,Z){return DJ(x,"toString",{configurable:!0,enumerable:!1,value:QV0(Z),writable:!0})},XV0=JV0,KV0=Date.now;HV0=VV0,GV0=HV0(XV0),SP=GV0;FV0=$V0;NV0=UV0;DV0=LV0,gR0=DV0(function(x,Z,Q,J){eK0(x,Z,Q,J)});BV0=OV0;MV0=vV0;SV0=RV0,fc=N6?N6.isConcatSpreadable:void 0;jV0=CV0;TV0=CP;cV0=IV0;AV0=qV0,PR0=AV0(function(x,Z){return x==null?{}:SV0(x,Z)}),EV0=W0(()=>R.object({allowedDomains:R.array(R.string()).optional(),deniedDomains:R.array(R.string()).optional().describe("Domains that are always blocked, even if matched by allowedDomains. Supports the same wildcard syntax as allowedDomains. Merged from all settings sources regardless of allowManagedDomainsOnly."),allowManagedDomainsOnly:R.boolean().optional().describe("When true (and set in managed settings), only allowedDomains and WebFetch(domain:...) allow rules from managed settings are respected. User, project, local, and flag settings domains are ignored. Denied domains are still respected from all sources."),allowUnixSockets:R.array(R.string()).optional().describe("macOS only: Unix socket paths to allow. Ignored on Linux (seccomp cannot filter by path)."),allowAllUnixSockets:R.boolean().optional().describe("If true, allow all Unix sockets (disables blocking on both platforms)."),allowLocalBinding:R.boolean().optional(),allowMachLookup:R.array(R.string().refine((x)=>!(x.endsWith("*")?x.slice(0,-1):x).includes("*"),{message:'Wildcards are only allowed as a single trailing "*" (e.g., "com.example.*" or "*" for all services).'})).optional().describe('macOS only: Additional XPC/Mach service names to allow looking up. Supports trailing-wildcard prefix matching (e.g., "com.apple.coresimulator.*"). Needed for tools that communicate via XPC such as the iOS Simulator or Playwright.'),httpProxyPort:R.number().optional(),socksProxyPort:R.number().optional(),tlsTerminate:R.object({caCertPath:R.string().min(1).optional(),caKeyPath:R.string().min(1).optional()}).optional().describe("[EXPERIMENTAL] Enable in-process TLS termination so the per-request filter can see HTTPS request bodies. Provide a CA cert+key, or omit both to have sandbox-runtime generate an ephemeral one for the session.")}).optional()),bV0=W0(()=>R.object({allowWrite:R.array(R.string()).optional().describe("Additional paths to allow writing within the sandbox. Merged with paths from Edit(...) allow permission rules."),denyWrite:R.array(R.string()).optional().describe("Additional paths to deny writing within the sandbox. Merged with paths from Edit(...) deny permission rules."),denyRead:R.array(R.string()).optional().describe("Additional paths to deny reading within the sandbox. Merged with paths from Read(...) deny permission rules."),allowRead:R.array(R.string()).optional().describe("Paths to re-allow reading within denyRead regions. Takes precedence over denyRead for matching paths."),allowManagedReadPathsOnly:R.boolean().optional().describe("When true (set in managed settings), only allowRead paths from policySettings are used.")}).optional()),kV0=W0(()=>R.object({enabled:R.boolean().optional(),failIfUnavailable:R.boolean().optional().describe("Exit with an error at startup if sandbox.enabled is true but the sandbox cannot start (missing dependencies or unsupported platform). When false (default), a warning is shown and commands run unsandboxed. Intended for managed-settings deployments that require sandboxing as a hard gate."),autoAllowBashIfSandboxed:R.boolean().optional(),allowUnsandboxedCommands:R.boolean().optional().describe("Allow commands to run outside the sandbox via the dangerouslyDisableSandbox parameter. When false, the dangerouslyDisableSandbox parameter is completely ignored and all commands must run sandboxed. Default: true."),network:EV0(),filesystem:bV0(),ignoreViolations:R.record(R.string(),R.array(R.string())).optional(),enableWeakerNestedSandbox:R.boolean().optional(),enableWeakerNetworkIsolation:R.boolean().optional().describe("macOS only: Allow access to com.apple.trustd.agent in the sandbox. Needed for Go-based CLI tools (gh, gcloud, terraform, etc.) to verify TLS certificates when using httpProxyPort with a MITM proxy and custom CA. "+"**Reduces security** — opens a potential data exfiltration vector through the trustd service. Default: false"),allowAppleEvents:R.boolean().optional().describe("macOS only: Allow sandboxed commands to send Apple Events (and look up the appleeventsd Mach service). Needed for `open`, `osascript`, and browser-based auth flows that open URLs. "+"**Removes code-execution isolation** — sandboxed commands can launch other applications "+"unsandboxed with no user prompt, and can script running apps (e.g. Terminal) subject to the user's per-app TCC automation consent. "+"Only honored from user, managed/policy, or CLI (--settings) settings — "+"project settings (.claude/settings.json and .claude/settings.local.json) are ignored. Default: false"),excludedCommands:R.array(R.string()).optional(),ripgrep:R.object({command:R.string(),args:R.array(R.string()).optional()}).optional().describe("Custom ripgrep configuration for bundled ripgrep support"),bwrapPath:R.preprocess((x)=>typeof x==="string"&&yc(x)?x:void 0,R.string()).optional().catch(void 0).describe("Linux/WSL only: Absolute path to the bwrap (bubblewrap) binary. Overrides auto-detection via PATH. Only honored from admin-controlled managed settings."),socatPath:R.preprocess((x)=>typeof x==="string"&&yc(x)?x:void 0,R.string()).optional().catch(void 0).describe("Linux/WSL only: Absolute path to the socat binary used for the sandbox network proxy. Overrides auto-detection via PATH. Only honored from admin-controlled managed settings.")}).passthrough()),gV0=["auto","iterm2","iterm2_with_bell","terminal_bell","kitty","ghostty","notifications_disabled"],PV0=["normal","vim"],wV0=["auto","tmux","in-process"],uV0=["dark","light","light-daltonized","dark-daltonized","light-ansi","dark-ansi"],fV0=["auto",...uV0],uR0=BP()==="macos"?"⏺":"●",KU=["acceptEdits","auto","bypassPermissions","default","dontAsk","plan"],yV0=[...KU,"bubble"],hV0=yV0,fR0=W0(()=>mg.enum(hV0)),yR0=W0(()=>mg.enum(KU)),mV0=["bash","powershell"],V2=W0(()=>R.string().optional().describe('Permission rule syntax to filter when this hook runs (e.g., "Bash(git *)"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.'));nV0=W0(()=>{let{BashCommandHookSchema:x,PromptHookSchema:Z,AgentHookSchema:Q,HttpHookSchema:J,McpToolHookSchema:X}=_V0();return R.discriminatedUnion("type",[x,Z,Q,J,X])}),lV0=W0(()=>R.object({matcher:R.string().optional().describe('String pattern to match (e.g. tool names like "Write")'),hooks:R.array(nV0()).describe("List of hooks to execute when the matcher matches")})),hJ=W0(()=>R.partialRecord(R.enum(vq),R.array(lV0()))),hR0=W0(()=>R.enum(["local","user","project","dynamic","enterprise","claudeai","managed","agent"])),mR0=W0(()=>R.enum(["stdio","sse","sse-ide","http","ws","sdk"])),N5=W0(()=>R.literal("comms").optional().catch(void 0)),B6=W0(()=>R.number().int().positive()),dV0=W0(()=>R.object({type:R.literal("stdio").optional(),command:R.string().min(1,"Command cannot be empty"),args:R.array(R.string()).default([]),env:R.record(R.string(),R.string()).optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5()})),iV0=W0(()=>R.boolean()),jP=W0(()=>R.object({clientId:R.string().optional(),callbackPort:R.number().int().positive().optional(),authServerMetadataUrl:R.string().url().startsWith("https://",{message:"authServerMetadataUrl must use https://"}).optional(),scopes:R.string().min(1).optional(),xaa:iV0().optional()})),pV0=W0(()=>R.object({type:R.literal("sse"),url:R.string(),headers:R.record(R.string(),R.string()).optional(),headersHelper:R.string().optional(),oauth:jP().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5(),toolPermissions:R.record(R.string(),VU()).optional()})),sV0=W0(()=>R.object({type:R.literal("sse-ide"),url:R.string(),ideName:R.string(),ideRunningInWindows:R.boolean().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5()})),oV0=W0(()=>R.object({type:R.literal("ws-ide"),url:R.string(),ideName:R.string(),authToken:R.string().optional(),ideRunningInWindows:R.boolean().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5()})),rV0=W0(()=>R.object({type:R.enum(["http","streamable-http"]).transform(()=>"http"),url:R.string(),headers:R.record(R.string(),R.string()).optional(),headersHelper:R.string().optional(),oauth:jP().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5(),toolPermissions:R.record(R.string(),VU()).optional()})),tV0=W0(()=>R.object({type:R.literal("ws"),url:R.string(),headers:R.record(R.string(),R.string()).optional(),headersHelper:R.string().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5()})),eV0=W0(()=>R.object({type:R.literal("sdk"),name:R.string(),timeout:B6().optional(),alwaysLoad:R.boolean().optional()})),VU=W0(()=>R.enum(["allow","ask","blocked"])),aV0=W0(()=>R.object({type:R.literal("claudeai-proxy"),url:R.string(),id:R.string(),displayName:R.string().optional(),iconUrl:R.string().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),toolPermissions:R.record(R.string(),VU()).optional(),stateless:R.boolean().optional(),cachedInitResponse:R.record(R.string(),R.unknown()).nullish()})),ZG=W0(()=>R.union([dV0(),pV0(),sV0(),oV0(),rV0(),tV0(),eV0(),aV0()])),_R0=W0(()=>R.object({mcpServers:R.record(R.string(),ZG())})),xH0=new Set(["claude-community","claude-plugins-community"]),YH0=new Set(["claude-code-marketplace","claude-code-plugins","claude-plugins-official","anthropic-marketplace","anthropic-plugins","agent-skills","anthropic-agent-skills","life-sciences","knowledge-work-plugins","claude-for-legal","claude-for-financial-services","financial-services-plugins"]),TP=new Set([...YH0,...xH0]),ZH0=/(?:official[^a-z0-9]*(anthropic|claude)|(?:anthropic|claude)[^a-z0-9]*official|^(?:anthropic|claude)[^a-z0-9]*(marketplace|plugins|official))/i,QH0=/[^\u0020-\u007E]/;A8=W0(()=>R.string().startsWith("./")),D3=W0(()=>A8().endsWith(".json")),hc=W0(()=>R.union([A8().refine((x)=>x.endsWith(".mcpb")||x.endsWith(".dxt"),{message:"MCPB file path must end with .mcpb or .dxt"}).describe("Path to MCPB file relative to plugin root"),R.string().url().refine((x)=>x.endsWith(".mcpb")||x.endsWith(".dxt"),{message:"MCPB URL must end with .mcpb or .dxt"}).describe("URL to MCPB file")])),QG=W0(()=>A8().endsWith(".md")),JG=W0(()=>R.union([QG(),A8()])),IP=W0(()=>R.string().min(1,"Marketplace must have a name").refine((x)=>!x.includes(" "),{message:'Marketplace name cannot contain spaces. Use kebab-case (e.g., "my-marketplace")'}).refine((x)=>!x.includes("/")&&!x.includes("\\")&&!x.includes("..")&&x!==".",{message:'Marketplace name cannot contain path separators (/ or \\), ".." sequences, or be "."'}).refine((x)=>!JH0(x),{message:"Marketplace name impersonates an official Anthropic/Claude marketplace"}).refine((x)=>x.toLowerCase()!=="inline",{message:'Marketplace name "inline" is reserved for --plugin-dir session plugins'}).refine((x)=>x.toLowerCase()!=="builtin",{message:'Marketplace name "builtin" is reserved for built-in plugins'}).refine((x)=>x.toLowerCase()!=="skills-dir",{message:'Marketplace name "skills-dir" is reserved for plugins auto-loaded from .claude/skills/'})),HU=W0(()=>R.object({name:R.string().min(1,"Author name cannot be empty").describe("Display name of the plugin author or organization"),email:R.string().optional().describe("Contact email for support or feedback"),url:R.string().optional().describe("Website, GitHub profile, or organization URL")})),XH0=W0(()=>R.object({$schema:R.string().optional().describe("JSON Schema reference for editor autocomplete/validation; ignored at load time"),name:R.string().min(1,"Plugin name cannot be empty").refine((x)=>!x.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Unique identifier for the plugin, used for namespacing (prefer kebab-case)"),displayName:R.string().optional().describe('Human-readable name shown in UI (e.g., "GitHub Utils"). Falls back to `name` when omitted. Unlike `name`, may contain spaces and any casing; not used for namespacing or lookup.'),version:R.string().optional().describe("Semantic version (e.g., 1.2.3) following semver.org specification"),description:R.string().optional().describe("Brief, user-facing explanation of what the plugin provides"),author:HU().optional().describe("Information about the plugin creator or maintainer"),homepage:R.string().url().optional().describe("Plugin homepage or documentation URL"),repository:R.string().optional().describe("Source code repository URL"),license:R.string().optional().describe("SPDX license identifier (e.g., MIT, Apache-2.0)"),keywords:R.array(R.string()).optional().describe("Tags for plugin discovery and categorization"),defaultEnabled:R.boolean().optional().describe("Whether the plugin starts enabled when the user has no explicit enabled/disabled setting for it (default: true). Explicit enabledPlugins values always win, and a plugin required by an enabled dependent is enabled regardless of this value."),dependencies:R.array(qH0()).optional().describe(`Plugins that must be enabled for this plugin to function. Bare names (no "@marketplace") are resolved against the declaring plugin's own marketplace.`)})),nR0=W0(()=>R.object({description:R.string().optional().describe("Brief, user-facing explanation of what these hooks provide"),hooks:R.lazy(()=>hJ()).describe("The hooks provided by the plugin, in the same format as the one used for settings")})),zH0=W0(()=>R.object({hooks:R.union([D3().describe("Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root"),R.lazy(()=>hJ()).describe("Additional hooks (in addition to those in hooks/hooks.json, if it exists)"),R.array(R.union([D3().describe("Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root"),R.lazy(()=>hJ()).describe("Additional hooks (in addition to those in hooks/hooks.json, if it exists)")]))])})),WH0=W0(()=>R.object({source:JG().optional().describe("Path to command markdown file, relative to plugin root"),content:R.string().optional().describe("Inline markdown content for the command"),description:R.string().optional().describe("Command description override"),argumentHint:R.string().optional().describe('Hint for command arguments (e.g., "[file]")'),model:R.string().optional().describe("Default model for this command"),allowedTools:R.array(R.string()).optional().describe("Tools allowed when command runs")}).refine((x)=>x.source&&!x.content||!x.source&&x.content,{message:'Command must have either "source" (file path) or "content" (inline markdown), but not both'})),KH0=W0(()=>R.object({commands:R.union([JG().describe("Path to a command file or skill directory, relative to the plugin root. When set, the commands/ directory is not auto-loaded — list its files here if you want both."),R.array(JG().describe("Path to a command file or skill directory, relative to the plugin root. When set, the commands/ directory is not auto-loaded — list its files here if you want both.")).describe("List of command file or skill directory paths. When set, the commands/ directory is not auto-loaded."),R.record(R.string(),WH0()).describe('Object mapping of command names to their metadata and source files. Command name becomes the slash command name (e.g., "about" → "/plugin:about")')])})),VH0=W0(()=>R.object({agents:R.union([QG().describe("Path to an agent file, relative to the plugin root. When set, the agents/ directory is not auto-loaded — list its files here if you want both."),R.array(QG().describe("Path to an agent file, relative to the plugin root. When set, the agents/ directory is not auto-loaded — list its files here if you want both.")).describe("List of agent file paths. When set, the agents/ directory is not auto-loaded.")])})),HH0=W0(()=>R.object({skills:R.union([A8().describe("Path to a skill directory, relative to the plugin root. Loaded in addition to the skills/ directory (except: for a marketplace entry whose source resolves to the marketplace root, declaring a specific subdirectory replaces the skills/ scan)."),R.array(A8().describe("Path to a skill directory, relative to the plugin root.")).describe("List of skill directory paths, loaded in addition to the skills/ directory (except: for a marketplace entry whose source resolves to the marketplace root, declaring specific subdirectories replaces the skills/ scan).")])})),cP=W0(()=>R.object({outputStyles:R.union([A8().describe("Path to an output-styles directory or file, relative to the plugin root. When set, the output-styles/ directory is not auto-loaded — list its files here if you want both."),R.array(A8().describe("Path to an output-styles directory or file, relative to the plugin root. When set, the output-styles/ directory is not auto-loaded — list its files here if you want both.")).describe("List of output-style directory or file paths. When set, the output-styles/ directory is not auto-loaded.")])})),qP=W0(()=>R.object({themes:R.union([A8().describe("Path to a themes directory or file, relative to the plugin root. When set, the themes/ directory is not auto-loaded — list its files here if you want both."),R.array(A8().describe("Path to a themes directory or file, relative to the plugin root. When set, the themes/ directory is not auto-loaded — list its files here if you want both.")).describe("List of theme directory or file paths. When set, the themes/ directory is not auto-loaded.")])})),GH0=W0(()=>R.object({})),mc=W0(()=>R.string().min(1)),$H0=W0(()=>R.string().min(2).refine((x)=>x.startsWith("."),{message:'File extensions must start with dot (e.g., ".ts", not "ts")'})),FH0=W0(()=>R.object({mcpServers:R.union([D3().describe("MCP servers to include in the plugin (in addition to those in the .mcp.json file, if it exists)"),hc().describe("Path or URL to MCPB file containing MCP server configuration"),R.record(R.string(),ZG()).describe("MCP server configurations keyed by server name"),R.array(R.union([D3().describe("Path to MCP servers configuration file"),hc().describe("Path or URL to MCPB file"),R.record(R.string(),ZG()).describe("Inline MCP server configurations")])).describe("Array of MCP server configurations (paths, MCPB files, or inline definitions)")])})),AP=W0(()=>R.object({type:R.enum(["string","number","boolean","directory","file"]).describe("Type of the configuration value"),title:R.string().describe("Human-readable label shown in the config dialog"),description:R.string().describe("Help text shown beneath the field in the config dialog"),required:R.boolean().optional().describe("If true, validation fails when this field is empty"),default:R.union([R.string(),R.number(),R.boolean(),R.array(R.string())]).optional().describe("Default value used when the user provides nothing"),multiple:R.boolean().optional().describe("For string type: allow an array of strings"),sensitive:R.boolean().optional().describe("If true, masks dialog input and stores value in secure storage (keychain/credentials file) instead of settings.json"),min:R.number().optional().describe("Minimum value (number type only)"),max:R.number().optional().describe("Maximum value (number type only)")}).strict()),UH0=W0(()=>R.object({userConfig:R.record(R.string().regex(/^[A-Za-z_]\w*$/,"Option keys must be valid identifiers (letters, digits, underscore; no leading digit) — they become CLAUDE_PLUGIN_OPTION_<KEY> env vars in hooks"),AP()).optional().describe("User-configurable values this plugin needs. Prompted at enable time. Non-sensitive values saved to settings.json; sensitive values to secure storage. Available as ${user_config.KEY} in MCP/LSP server config, hook commands, and (non-sensitive only) skill/agent content. Keep sensitive value counts small.")})),NH0=W0(()=>R.object({channels:R.array(R.object({server:R.string().min(1).describe("Name of the MCP server this channel binds to. Must match a key in this plugin's mcpServers."),displayName:R.string().optional().describe('Human-readable name shown in the config dialog title (e.g., "Telegram"). Defaults to the server name.'),userConfig:R.record(R.string(),AP()).optional().describe("Fields to prompt the user for when enabling this plugin in assistant mode. Saved values are substituted into ${user_config.KEY} references in the mcpServers env.")}).strict()).describe("Channels this plugin provides. Each entry declares an MCP server as a message channel and optionally specifies user configuration to prompt for at enable time.")})),_c=W0(()=>R.strictObject({command:R.string().min(1).refine((x)=>{if(x.includes(" ")&&!x.startsWith("/"))return!1;return!0},{message:"Command should not contain spaces. Use args array for arguments."}).describe('Command to execute the LSP server (e.g., "typescript-language-server")'),args:R.array(mc()).optional().describe("Command-line arguments to pass to the server"),extensionToLanguage:R.record($H0(),mc()).refine((x)=>Object.keys(x).length>0,{message:"extensionToLanguage must have at least one mapping"}).describe("Mapping from file extension to LSP language ID. File extensions and languages are derived from this mapping."),transport:R.enum(["stdio","socket"]).default("stdio").describe("Communication transport mechanism"),env:R.record(R.string(),R.string()).optional().describe("Environment variables to set when starting the server"),initializationOptions:R.unknown().optional().describe("Initialization options passed to the server during initialization"),settings:R.unknown().optional().describe("Settings passed to the server via workspace/didChangeConfiguration"),workspaceFolder:R.string().optional().describe("Workspace folder path to use for the server"),startupTimeout:R.number().int().positive().optional().describe("Maximum time to wait for server startup (milliseconds)"),shutdownTimeout:R.number().int().positive().optional().describe("Maximum time to wait for graceful shutdown (milliseconds)"),restartOnCrash:R.boolean().optional().describe("Whether to restart the server if it crashes"),maxRestarts:R.number().int().nonnegative().optional().describe("Maximum number of restart attempts before giving up"),diagnostics:R.boolean().optional().describe("Whether to push publishDiagnostics into the agent context after edits. Set to false to keep LSP navigation (goToDefinition, hover, etc.) but suppress automatic diagnostic injection. Defaults to true.")})),LH0=W0(()=>R.strictObject({name:R.string().min(1).describe("Identifier for this monitor, unique within the plugin. Used to dedupe so re-arming (plugin reload, repeat skill invoke) does not spawn duplicates."),command:R.string().min(1).describe('Shell command to run as a persistent background monitor. Each stdout line is delivered to the model as a <task_notification> event; the process runs for the session lifetime. ${CLAUDE_PLUGIN_ROOT}, ${CLAUDE_PLUGIN_DATA}, ${CLAUDE_PROJECT_DIR}, ${user_config.*}, and ${ENV_VAR} are substituted. Runs in the session cwd — prefix with `cd "${CLAUDE_PLUGIN_ROOT}" && ` if the script needs its own directory.'),description:R.string().min(1).describe("Short human-readable description of what is being monitored (shown in task panel and notification summary)."),when:R.union([R.literal("always"),R.string().startsWith("on-skill-invoke:").refine((x)=>x.length>16,{message:"on-skill-invoke: must specify a skill name"})]).default("always").describe('Arm trigger. "always" arms at session start and on plugin reload. "on-skill-invoke:<skill>" arms the first time that skill is dispatched (via Skill tool or slash command).')})),DH0=W0(()=>R.array(LH0()).refine((x)=>new Set(x.map((Z)=>Z.name)).size===x.length,{message:"Monitor names must be unique within a plugin"})),EP=W0(()=>R.object({monitors:R.union([D3().describe("Path to a JSON file containing the monitors array, relative to the plugin root"),DH0()]).describe("Background watch scripts the host arms as persistent Monitor tasks (unsandboxed, same trust tier as hooks) so plugins need not instruct the model to arm them. When omitted, monitors/monitors.json at the plugin root is loaded if present.")})),OH0=W0(()=>R.object({lspServers:R.union([D3().describe("Path to .lsp.json configuration file relative to plugin root"),R.record(R.string(),_c()).describe("LSP server configurations keyed by server name"),R.array(R.union([D3().describe("Path to LSP configuration file"),R.record(R.string(),_c()).describe("Inline LSP server configurations")])).describe("Array of LSP server configurations (paths or inline definitions)")])})),bP=W0(()=>R.string().refine((x)=>!x.includes("..")&&!x.includes("//"),"Package name cannot contain path traversal patterns").refine((x)=>{let Z=/^@[a-z0-9][a-z0-9-._]*\/[a-z0-9][a-z0-9-._]*$/,Q=/^[a-z0-9][a-z0-9-._]*$/;return Z.test(x)||Q.test(x)},"Invalid npm package name format")),BH0=W0(()=>R.object({settings:R.record(R.string(),R.unknown()).optional().describe("Settings to merge into the user settings while this plugin is enabled. Only the documented allowlisted keys are applied.")})),vH0=W0(()=>R.object({experimental:R.preprocess((x)=>typeof x==="object"&&x!==null&&!Array.isArray(x)?x:void 0,R.object({...qP().partial().shape,...EP().partial().shape,...cP().partial().shape,evals:R.union([R.string(),R.array(R.string())]).optional().describe("Path(s) to evaluation query files for `claude plugin eval`. Defaults to `evals/`.")}).optional().describe("Components whose manifest shape may change without a deprecation cycle. Move a key out of here once it is promoted to stable."))})),MH0=W0(()=>R.object({...XH0().shape,...zH0().partial().shape,...KH0().partial().shape,...VH0().partial().shape,...HH0().partial().shape,...cP().partial().shape,...qP().partial().shape,...GH0().shape,...NH0().partial().shape,...FH0().partial().shape,...OH0().partial().shape,...EP().partial().shape,...BH0().partial().shape,...UH0().partial().shape,...vH0().partial().shape})),mJ=W0(()=>R.discriminatedUnion("source",[R.object({source:R.literal("url"),url:R.string().url().describe("Direct URL to marketplace.json file"),headers:R.record(R.string(),R.string()).optional().describe("Custom HTTP headers (e.g., for authentication)")}),R.object({source:R.literal("github"),repo:R.string().describe("GitHub repository in owner/repo format"),ref:R.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),path:R.string().optional().describe("Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"),sparsePaths:R.array(R.string()).optional().describe('Directories to include via git sparse-checkout (cone mode). Use for monorepos where the marketplace lives in a subdirectory. Example: [".claude-plugin", "plugins"]. If omitted, the full repository is cloned.'),skipLfs:R.boolean().optional().describe("Skip Git LFS smudge during clone and update (sets GIT_LFS_SKIP_SMUDGE=1) so LFS pointer files stay as pointers instead of downloading their content. Use for marketplaces hosted in repos with large LFS objects.")}),R.object({source:R.literal("git"),url:R.string().describe("Full git repository URL"),ref:R.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),path:R.string().optional().describe("Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"),sparsePaths:R.array(R.string()).optional().describe('Directories to include via git sparse-checkout (cone mode). Use for monorepos where the marketplace lives in a subdirectory. Example: [".claude-plugin", "plugins"]. If omitted, the full repository is cloned.'),skipLfs:R.boolean().optional().describe("Skip Git LFS smudge during clone and update (sets GIT_LFS_SKIP_SMUDGE=1) so LFS pointer files stay as pointers instead of downloading their content. Use for marketplaces hosted in repos with large LFS objects.")}),R.object({source:R.literal("npm"),package:bP().describe("NPM package containing marketplace.json")}),R.object({source:R.literal("file"),path:R.string().describe("Local file path to marketplace.json")}),R.object({source:R.literal("directory"),path:R.string().describe("Local directory containing .claude-plugin/marketplace.json")}),R.object({source:R.literal("skills-dir")}).describe("Policy-list sentinel for the ~/.claude/skills/ auto-load (@skills-dir plugins). In strictKnownMarketplaces: opt the scan back IN (by default any allowlist blocks it). In blockedMarketplaces: turn the scan OFF without otherwise restricting marketplaces. Only meaningful in those two managed-settings lists (areLocalPluginDirsAllowedByPolicy); known_marketplaces.json / marketplace add etc. ignore it."),R.object({source:R.literal("hostPattern"),hostPattern:R.string().describe('Regex pattern to match the host/domain extracted from any marketplace source type. For github sources, matches against "github.com". For git sources (SSH or HTTPS), extracts the hostname from the URL. Use in strictKnownMarketplaces to allow all marketplaces from a specific host (e.g., "^github\\.mycompany\\.com$").')}),R.object({source:R.literal("pathPattern"),pathPattern:R.string().describe('Regex pattern matched against the .path field of file and directory sources. Use in strictKnownMarketplaces to allow filesystem-based marketplaces alongside hostPattern restrictions for network sources. Use ".*" to allow all filesystem paths, or a narrower pattern (e.g., "^/opt/approved/") to restrict to specific directories.')}),R.object({source:R.literal("settings"),name:IP().refine((x)=>!TP.has(x.toLowerCase()),{message:"Reserved marketplace names cannot be used with settings sources. validateOfficialNameSource only accepts github/git sources from anthropics/* for these names; a settings source would be rejected after loadAndCacheMarketplace has already written to disk with cleanupNeeded=false."}).describe("Marketplace name. Must match the extraKnownMarketplaces key (enforced); the synthetic manifest is written under this name. Same validation "+"as PluginMarketplaceSchema plus reserved-name rejection — "+"validateOfficialNameSource runs after the disk write, too late to clean up."),plugins:R.array(RH0()).describe("Plugin entries declared inline in settings.json"),owner:HU().optional()}).describe("Inline marketplace manifest defined directly in settings.json. The reconciler writes a synthetic marketplace.json to the cache; diffMarketplaces detects edits via isEqual on the stored source (the plugins array is inside this object, so edits surface as sourceChanged).")])),cH=W0(()=>R.string().length(40).regex(/^[a-f0-9]{40}$/,"Must be a full 40-character lowercase git commit SHA")),kP=W0(()=>R.union([R.preprocess((x)=>x==="."?"./":x,A8()).describe("Path to the plugin root, relative to the marketplace root (the directory containing .claude-plugin/, not .claude-plugin/ itself)"),R.object({source:R.literal("npm"),package:bP().or(R.string().refine((x)=>/^(?:file|https?|git(?:\+https?|\+ssh)?|ssh|github|gitlab|bitbucket):/i.test(x)||!x.includes(".."),'Package reference cannot contain ".." path segments')).describe("Package name (or url, or local path, or anything else that can be passed to `npm` as a package)"),version:R.string().optional().describe("Specific version or version range (e.g., ^1.0.0, ~2.1.0)"),registry:R.string().url().optional().describe("Custom NPM registry URL (defaults to using system default, likely npmjs.org)")}).describe("NPM package as plugin source"),R.object({source:R.literal("url"),url:R.string().describe("Full git repository URL (https:// or git@)"),ref:R.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:cH().optional().describe("Specific commit SHA to use")}),R.object({source:R.literal("github"),repo:R.string().describe("GitHub repository in owner/repo format"),ref:R.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:cH().optional().describe("Specific commit SHA to use")}),R.object({source:R.literal("git-subdir"),url:R.string().describe("Git repository: GitHub owner/repo shorthand, https://, or git@ URL"),path:R.string().min(1).describe('Subdirectory within the repo containing the plugin (e.g., "tools/claude-plugin"). Cloned sparsely using partial clone (--filter=tree:0) to minimize bandwidth for monorepos.'),ref:R.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:cH().optional().describe("Specific commit SHA to use")}).describe("Plugin located in a subdirectory of a larger repository (monorepo). Only the specified subdirectory is materialized; the rest of the repo is not downloaded."),R.object({source:R.literal("unsupported")}).describe("Placeholder for source types this Claude Code version does not "+"recognize. Never authored by hand — PluginMarketplaceSchema rewrites "+'unparseable sources to this so the entry remains in marketplace.plugins (detectDelistedPlugins must not see it as removed). Install attempts fail at cachePlugin with a clear "update Claude Code" message.')])),RH0=W0(()=>R.object({name:R.string().min(1,"Plugin name cannot be empty").refine((x)=>!x.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Plugin name as it appears in the target repository"),source:kP().describe("Where to fetch the plugin from. Must be a remote source — relative "+"paths have no marketplace repository to resolve against."),description:R.string().optional(),version:R.string().optional(),strict:R.boolean().optional()}).refine((x)=>typeof x.source!=="string",{message:'Plugins in a settings-sourced marketplace must use remote sources (github, git-subdir, npm, url). Relative-path sources like "./foo" have no marketplace repository to resolve against.'}).refine((x)=>typeof x.source==="string"||x.source.source!=="unsupported",{message:"source.source: 'unsupported' is a parse-time placeholder and cannot be authored. Use a remote source (github, git-subdir, npm, url)."})),SH0=W0(()=>R.object({cli:R.array(R.string().max(64)).max(10).optional().describe('First command tokens (e.g. ["stripe"]) — exact match against commands run this session.'),hosts:R.array(R.string().max(128)).max(20).optional().describe('Hostnames (e.g. ["api.stripe.com"]) — exact, case-insensitive match against '+"hostnames seen in https?:// URLs in bash commands run this session. Bare hostname only: lowercase, no scheme, no port, no path."),filesRead:R.array(R.string().max(256)).max(10).optional().describe('Glob patterns (e.g. ["**/*.tf"]) — the plugin is relevant when a file Claude has read '+"this session matches any pattern. Matched against read-file paths, forward-slash normalized, case-insensitive."),manifestDeps:R.array(R.object({file:R.string().max(256),pattern:R.string().max(256)})).max(10).optional().describe("Dependency declared in a package manifest. Each {file, pattern} is a pair of RegExp sources: "+"`file` matches the manifest filename (package.json, go.mod, requirements.txt, …); "+"`pattern` matches the dependency declaration inside that file. Evaluated against files read this session."),cwd:R.array(R.string().max(256)).max(10).optional().describe('Glob patterns (e.g. ["Engine/Source/Runtime/Renderer/**"]) — the plugin is relevant when the '+`session's working directory is at or under a directory matching the pattern. Matched against the cwd both relative to the enclosing git repo root and as an absolute path, forward-slash normalized, case-insensitive. A bare directory (no glob characters) means "cwd is at or under this directory". Known at session start, so this signal can surface a suggestion before the first turn.`)})),CH0=W0(()=>R.object({topic:R.string().max(64).optional().describe('What the user is working with when this plugin is relevant — fills "Working with {topic}?". '+'Often the product name (e.g. "Stripe"); use a domain (e.g. "design") when the plugin name does not read naturally as a topic. Defaults to the plugin name with each hyphen-segment capitalized.'),signals:SH0().optional().describe("Matchers that determine when the plugin is relevant.")})),jH0=W0(()=>MH0().partial().extend({name:R.string().min(1,"Plugin name cannot be empty").refine((x)=>!x.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Unique identifier matching the plugin name"),source:kP().describe("Where to fetch the plugin from"),category:R.string().optional().describe('Category for organizing plugins (e.g., "productivity", "development")'),tags:R.array(R.string()).optional().describe("Tags for searchability and discovery"),strict:R.boolean().optional().default(!0).describe("Require the plugin manifest to be present in the plugin folder. If false, the marketplace entry provides the manifest."),relevance:R.preprocess((x)=>typeof x==="object"&&x!==null&&!Array.isArray(x)?x:void 0,CH0().optional()).describe(`Declares when this plugin is relevant to the user's work. Consumed by the spinner tip ("Working with {topic}?"), session-start auto-suggest, and marketplace browse ranking.`)})),TH0=W0(()=>R.object({name:R.string().min(1).refine((x)=>!x.includes(" "))}));lR0=W0(()=>R.object({$schema:R.string().optional().describe("JSON Schema reference for editor autocomplete/validation; ignored at load time"),name:IP(),version:R.string().optional().describe("Marketplace manifest version"),description:R.string().optional().describe("Human-readable description of this marketplace"),owner:HU().describe("Marketplace maintainer or curator information"),plugins:R.array(R.unknown()).transform(IH0).describe("Collection of available plugins in this marketplace"),forceRemoveDeletedPlugins:R.boolean().optional().describe("When true, plugins removed from this marketplace will be automatically uninstalled and flagged for users"),metadata:R.object({pluginRoot:R.string().optional().describe("Base path for relative plugin sources"),version:R.string().optional().describe("Marketplace version"),description:R.string().optional().describe("Marketplace description")}).optional().describe("Optional marketplace metadata"),allowCrossMarketplaceDependenciesOn:R.array(R.string()).optional().describe("Marketplace names whose plugins may be auto-installed as dependencies. Only the root marketplace's allowlist applies — no transitive trust.")})),gP=W0(()=>R.string().regex(/^[A-Za-z0-9][-A-Za-z0-9._]*@[A-Za-z0-9][-A-Za-z0-9._]*$/,"Plugin ID must be in format: plugin@marketplace")),cH0=/^[A-Za-z0-9][-A-Za-z0-9._]*(@[A-Za-z0-9][-A-Za-z0-9._]*)?(@\^[^@]*)?$/,qH0=W0(()=>R.union([R.string().regex(cH0,"Dependency must be a plugin name, optionally qualified with @marketplace").transform((x)=>x.replace(/@\^[^@]*$/,"")),R.object({name:R.string().min(1).regex(/^[A-Za-z0-9][-A-Za-z0-9._]*$/),marketplace:R.string().min(1).regex(/^[A-Za-z0-9][-A-Za-z0-9._]*$/).optional()}).loose().transform((x)=>x.marketplace?`${x.name}@${x.marketplace}`:x.name)])),AH0=W0(()=>R.object({version:R.string().describe("Currently installed version"),installedAt:R.string().describe("ISO 8601 timestamp of installation"),lastUpdated:R.string().optional().describe("ISO 8601 timestamp of last update"),installPath:R.string().describe("Absolute path to the installed plugin directory"),gitCommitSha:R.string().optional().describe("Git commit SHA for git-based plugins (for version tracking)"),resolvedVersion:R.string().optional().describe("Tag-derived semver this install resolved to (when fetched via a version constraint). Used by verifyAndDemote in preference to manifest.version, since the upstream may have forgotten to bump plugin.json."),auto:R.boolean().optional().describe("True when this plugin was pulled in as a dependency rather than installed explicitly. Auto-installed plugins are eligible for removal by the orphan sweep when nothing depends on them. Absent = manual (preserves pre-flag installs).")})),EH0=W0(()=>R.object({version:R.literal(1).describe("Schema version 1"),plugins:R.record(gP(),AH0()).describe("Map of plugin IDs to their installation metadata")})),bH0=W0(()=>R.enum(["managed","user","project","local"])),kH0=W0(()=>R.object({scope:bH0().describe("Installation scope"),projectPath:R.string().optional().describe("Project path (required for project/local scopes)"),installPath:R.string().describe("Absolute path to the versioned plugin directory"),version:R.string().optional().describe("Currently installed version"),installedAt:R.string().optional().describe("ISO 8601 timestamp of installation"),lastUpdated:R.string().optional().describe("ISO 8601 timestamp of last update"),gitCommitSha:R.string().optional().describe("Git commit SHA for git-based plugins"),resolvedVersion:R.string().optional().describe("Tag-derived semver this install resolved to"),auto:R.boolean().optional().describe("True when pulled in as a dependency. Eligible for orphan sweep.")})),gH0=W0(()=>R.object({version:R.literal(2).describe("Schema version 2"),plugins:R.record(gP(),R.array(kH0())).describe("Map of plugin IDs to arrays of installation entries")})),dR0=W0(()=>R.union([EH0(),gH0()])),PH0=W0(()=>R.object({source:mJ().describe("Where to fetch the marketplace from"),installLocation:R.string().describe("Local cache path where marketplace manifest is stored"),lastUpdated:R.string().describe("ISO 8601 timestamp of last marketplace refresh"),autoUpdate:R.boolean().optional().describe("Whether to automatically update this marketplace and its installed plugins on startup")})),iR0=W0(()=>R.record(R.string(),PH0())),wH0=["autoMode","deepLink","voice","briefView","screenReader"],XJ={},bX={autoMode:{buildGate:()=>!1,shape:()=>XJ,permissionsShape:()=>XJ,permissionModes:()=>[]},deepLink:{buildGate:()=>!0,shape:()=>({disableDeepLinkRegistration:R.enum(["disable"]).optional().describe("Prevent claude-cli:// protocol handler registration with the OS")})},voice:{buildGate:()=>!1,shape:()=>XJ},briefView:{buildGate:()=>!0,shape:()=>({defaultView:R.enum(["chat","transcript"]).optional().describe("Default transcript view: chat (SendUserMessage checkpoints only) or transcript (full)")})},screenReader:{buildGate:()=>!1,shape:()=>XJ}};nc={Task:"Agent",KillShell:"TaskStop",KillBash:"TaskStop",AgentOutputTool:"TaskOutput",BashOutputTool:"TaskOutput",AgentOutput:"TaskOutput",BashOutput:"TaskOutput",ListPeers:"ListAgents",Brief:"SendUserMessage",ListMcpResources:"ListMcpResourcesTool",ReadMcpResource:"ReadMcpResourceTool"};pR0=`mcp__${uP}__bash`,sR0=`mcp__${uP}__web_fetch`;_J={filePatternTools:["Read","Write","Edit","Glob","NotebookRead","NotebookEdit","Cd"],bashPrefixTools:["Bash"],customValidation:{WebSearch:(x)=>{if(x.includes("*")||x.includes("?"))return{valid:!1,error:"WebSearch does not support wildcards",suggestion:"Use exact search terms without * or ?",examples:["WebSearch(claude ai)","WebSearch(typescript tutorial)"]};return{valid:!0}},WebFetch:(x)=>{if(x.includes("://")||x.startsWith("http"))return{valid:!1,error:"WebFetch permissions use domain format, not URLs",suggestion:'Use "domain:hostname" format',examples:["WebFetch(domain:example.com)","WebFetch(domain:github.com)"]};if(!x.startsWith("domain:"))return{valid:!1,error:'WebFetch permissions must use "domain:" prefix',suggestion:'Use "domain:hostname" format',examples:["WebFetch(domain:example.com)","WebFetch(domain:*.google.com)"]};return{valid:!0}}}};ic=W0(()=>yP()),oH0=W0(()=>yP("allow"));rH0=W0(()=>R.record(R.string(),R.coerce.string()));oR0=W0(()=>hP(PP())),tH0=W0(()=>R.object({source:mJ().describe("Where to fetch the marketplace from"),installLocation:R.string().optional().describe("Local cache path where marketplace manifest is stored (auto-generated if not provided)"),autoUpdate:R.boolean().optional().describe("Whether to automatically update this marketplace and its installed plugins on startup")})),eH0=W0(()=>R.object({serverName:R.string().regex(/^[a-zA-Z0-9_-]+$/,"Server name can only contain letters, numbers, hyphens, and underscores").optional().describe("Name of the MCP server that users are allowed to configure"),serverCommand:R.array(R.string()).min(1,"Server command must have at least one element (the command)").optional().describe("Command array [command, ...args] to match exactly for allowed stdio servers"),serverUrl:R.string().optional().describe('URL pattern with wildcard support (e.g., "https://*.example.com/*") for allowed remote MCP servers')}).refine((x)=>fA([x.serverName!==void 0,x.serverCommand!==void 0,x.serverUrl!==void 0],Boolean)===1,{message:'Entry must have exactly one of "serverName", "serverCommand", or "serverUrl"'})),aH0=W0(()=>R.object({serverName:R.string().regex(/^[a-zA-Z0-9_-]+$/,"Server name can only contain letters, numbers, hyphens, and underscores").optional().describe("Name of the MCP server that is explicitly blocked"),serverCommand:R.array(R.string()).min(1,"Server command must have at least one element (the command)").optional().describe("Command array [command, ...args] to match exactly for blocked stdio servers"),serverUrl:R.string().optional().describe('URL pattern with wildcard support (e.g., "https://*.example.com/*") for blocked remote MCP servers')}).refine((x)=>fA([x.serverName!==void 0,x.serverCommand!==void 0,x.serverUrl!==void 0],Boolean)===1,{message:'Entry must have exactly one of "serverName", "serverCommand", or "serverUrl"'})),xG0=W0(()=>R.object({path:R.string().describe("Absolute path to the helper executable"),timeoutMs:R.number().int().min(1000).optional(),refreshIntervalMs:R.union([R.literal(0),R.number().int().min(60000)]).optional()})),pc=["skills","agents","hooks","mcp"],sc=Object.freeze({type:"invalid-entry-stripped"}),YG0=W0(()=>R.union([R.object({type:R.literal("regex").describe('Config variant. This client understands "regex": matches turn output and builds a URL from named capture groups. Entries with other variants are preserved but skipped at runtime.'),pattern:R.string().describe("Regex matched against turn output (tool results and assistant text)"),url:R.string().describe("Link target. {name} placeholders are filled from named regex capture groups, e.g. (?<id>...) -> {id}. Values are URL-encoded; the origin must be literal in the template. The scheme must be https, http, or a recognized editor or workspace deep-link scheme: vscode, vscode-insiders, cursor, windsurf, zed, jetbrains, idea, slack, linear, notion, figma."),label:R.string().optional().describe("Badge text. {name} placeholders filled from named capture groups; defaults to the full match.")}).passthrough(),R.object({type:R.string().describe("Config variant discriminator for entries this client does not understand; the entry is preserved as-is and skipped at runtime.")}).passthrough()]));QG0=W0(()=>ZG0(PP())),rR0=Object.freeze({serverName:"invalid-entry-stripped"}),tR0=[{matches:(x)=>x.path==="permissions.defaultMode"&&x.code==="invalid_value",tip:{suggestion:'Valid modes: "acceptEdits" (ask before file changes), "plan" (analysis only), "bypassPermissions" (auto-accept all), or "default" (standard behavior)',docLink:`${A4}/iam#permission-modes`}},{matches:(x)=>x.path==="apiKeyHelper"&&x.code==="invalid_type",tip:{suggestion:'Provide a shell command that outputs your API key to stdout. The script should output only the API key. Example: "/bin/generate_temp_api_key.sh"'}},{matches:(x)=>x.path==="cleanupPeriodDays"&&x.code==="too_small",tip:{suggestion:'cleanupPeriodDays must be at least 1. To keep transcripts for a long time, set a large number (e.g. 3650 for ~10 years). To disable transcript writes entirely, remove this setting and use the --no-session-persistence CLI flag or the SDK persistSession:false option instead. (0 is rejected because it previously silently disabled all transcript writes, which users setting it to mean "never clean up" did not expect.)'}},{matches:(x)=>x.path.startsWith("env.")&&x.code==="invalid_type",tip:{suggestion:'Environment variables must be strings. Wrap numbers and booleans in quotes. Example: "DEBUG": "true", "PORT": "3000"',docLink:`${A4}/settings#environment-variables`}},{matches:(x)=>(x.path==="permissions.allow"||x.path==="permissions.deny")&&x.code==="invalid_type"&&x.expected==="array",tip:{suggestion:'Permission rules must be in an array. Format: ["Tool(specifier)"]. Examples: ["Bash(npm run build)", "Edit(docs/**)", "Read(~/.zshrc)"]. Use * for wildcards.'}},{matches:(x)=>x.path.startsWith("hooks.")&&x.code==="invalid_key",tip:{suggestion:"Not a recognized hook event. Common events: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd, Stop. Check spelling and capitalization.",docLink:`${A4}/hooks`}},{matches:(x)=>/\.hooks\.\d+\.command$/.test(x.path)&&x.code==="invalid_type"&&x.received==="undefined",tip:{suggestion:'Command hooks require `command`. For exec form (no shell), set `command` to the executable and `args` to its arguments: {"type": "command", "command": "echo", "args": ["hi"]}. For shell form, set `command` to the full shell string: {"type": "command", "command": "echo hi"}.',docLink:`${A4}/hooks#exec-form-and-shell-form`}},{matches:(x)=>x.path.includes("hooks")&&x.code==="invalid_type",tip:{suggestion:'Hooks use a matcher + hooks array. The matcher is a string: a tool name ("Bash"), pipe-separated list ("Edit|Write"), or empty to match all. Example: {"PostToolUse": [{"matcher": "Edit|Write", "hooks": [{"type": "command", "command": "echo Done"}]}]}'}},{matches:(x)=>x.code==="invalid_type"&&x.expected==="boolean",tip:{suggestion:'Use true or false without quotes. Example: "includeCoAuthoredBy": true'}},{matches:(x)=>x.code==="unrecognized_keys",tip:{suggestion:"Check for typos or refer to the documentation for valid fields",docLink:`${A4}/settings`}},{matches:(x)=>x.code==="invalid_value"&&x.enumValues!==void 0,tip:{suggestion:void 0}},{matches:(x)=>x.code==="invalid_type"&&x.expected==="object"&&x.received===null&&x.path==="",tip:{suggestion:"Check for missing commas, unmatched brackets, or trailing commas. Use a JSON validator to identify the exact syntax error."}},{matches:(x)=>x.path==="permissions.additionalDirectories"&&x.code==="invalid_type",tip:{suggestion:'Must be an array of directory paths. Example: ["~/projects", "/tmp/workspace"]. You can also use --add-dir flag or /add-dir command',docLink:`${A4}/iam#working-directories`}}],eR0={permissions:`${A4}/iam#configuring-permissions`,env:`${A4}/settings#environment-variables`,hooks:`${A4}/hooks`},aR0=W0(()=>QG0().strict()),xS0=new Set(vq),YS0=Object.freeze({settings:{},errors:[]});process.env.NoDefaultCurrentDirectoryInExePath="1";KG0=new Set(["EBUSY","EMFILE","ENFILE","ENOTEMPTY","EPERM"])});function $G0(x){return{...dP[x]??{},..._x.claude.models[x]??{}}}function FG0(x){let Z=$G0(x);return{key:`claude:${x}`,name:x,displayName:Z.display_name?.trim()||`Claude Code · ${x}`,description:Z.description?.trim()||`使用 ${x} 路由运行 Claude Code 后端。`,sdkModel:Z.model?.trim()||"opus"}}function UG0(){return[...new Set([...Object.keys(dP),...Object.keys(_x.claude.models)])].map(FG0).filter((Z)=>Z!==null)}function NG0(x){if(!x?.startsWith("claude:"))return null;let Z=x.slice(7);if(!Z||Z==="default")return null;return UG0().find((Q)=>Q.name===Z||Q.key===x)??null}function v6(x){return x.startsWith("claude:")?x:`claude:${x}`}function GU(x){if(!x)return"opus";let Z=NG0(x);if(Z)return Z.sdkModel;let Q=x.startsWith("claude:")?x.slice(7):x;return Q==="default"?"opus":Q}var dP;var iP=E0(()=>{Z3();dP={glm:{display_name:"Claude Code · GLM",description:"使用 GLM 路由,适合中文交流和通用编码任务。"}}});import{existsSync as NU,readFileSync as eP}from"node:fs";import{homedir as zY}from"node:os";import{spawn as LG0}from"node:child_process";import{delimiter as pP,join as M3,posix as DG0,win32 as OG0}from"node:path";import{EventEmitter as BG0}from"node:events";function vG0(x){return x==="win32"?";":":"}function FU(x,...Z){return x==="win32"?OG0.join(...Z):DG0.join(...Z)}function sP(x){let Z=x.toLowerCase();return Z.endsWith(".cmd")||Z.endsWith(".bat")}function oP(x){let Z=LG0(x.command,x.args,{cwd:x.cwd,env:x.env,shell:!0,signal:x.signal,stdio:["pipe","pipe","ignore"],windowsHide:!0});if(!Z.stdin||!Z.stdout)throw Z.kill(),Error("failed to open stdio for Claude Code Windows shell shim");return Z}function xw(x={}){let Z=x.platform??process.platform,Q=x.exists??NU,J=x.homeDir??zY();if(Z!=="win32"){let z=[FU(Z,J,".local","npm-global","bin","claude"),FU(Z,J,".local","bin","claude")];for(let Y of z)if(Q(Y))return Y}let X=RG0(x);if(X)return X;return null}function Yw(){xw()}function MG0(x={}){let Z=x.platform??process.platform,Q=x.configuredBin===void 0?_x.claude.bin:x.configuredBin;if(Q){if(!(x.exists??NU)(Q))throw Error(`lodestar: [claude].bin not found: ${Q} (config.toml)`);if(Z==="win32"&&sP(Q))return{pathToClaudeCodeExecutable:Q,spawnClaudeCodeProcess:oP,description:`windows-shell-shim:${Q}`};return{pathToClaudeCodeExecutable:Q,description:`config:${Q}`}}let J=xw(x);if(!J)return{description:"sdk-default"};if(Z==="win32"&&sP(J))return{pathToClaudeCodeExecutable:J,spawnClaudeCodeProcess:oP,description:`windows-shell-shim:${J}`};return{pathToClaudeCodeExecutable:J,description:J}}function RG0(x={}){let Z=x.platform??process.platform,Q=x.pathEnv??process.env.PATH??"";if(!Q)return null;let J=x.exists??NU,X=Z==="win32"?["claude.exe","claude.cmd","claude.bat","claude"]:["claude"];for(let z of Q.split(vG0(Z))){if(!z)continue;for(let Y of X){let G=FU(Z,z,Y);if(J(G))return G}}return null}function SG0(){if(process.platform==="win32")return process.env.PATH??"";let x=[M3(zY(),".local","npm-global","bin"),M3(zY(),".local","bin"),M3(zY(),".bun","bin"),...(process.env.PATH??"").split(pP),"/usr/local/bin","/usr/bin","/bin"];return[...new Set(x.filter(Boolean))].join(pP)}function CG0(x){let Z=E7(x);if(!Z)return null;let Q=(Z.input_tokens??0)+(Z.output_tokens??0)+(Z.cache_creation_input_tokens??0)+(Z.cache_read_input_tokens??0);if((Z.total_tokens??Q)<=0)return null;if(Z.total_tokens==null)Z.total_tokens=Q;return Z}function jG0(x){if(!x)return null;let Z=(x.input_tokens??0)+(x.cache_read_input_tokens??0)+(x.cache_creation_input_tokens??0);return Z>0?Z:null}function LU(x){let Z=x.replace(/\//g,"-"),Q=process.env.CLAUDE_CONFIG_DIR||M3(zY(),".claude");return M3(Q,"projects",Z)}function TG0(x,Z){return M3(LU(x),`${Z}.jsonl`)}function IG0(x){let Z;try{Z=eP(x,"utf8")}catch{return null}let Q=Z.split(`
221
+ `)){let J=Q.match(/^(ID|VERSION_ID)=(.*)$/);if(J&&J[1]&&J[2]){let X=J[2].replace(/^"|"$/g,"");if(J[1]==="ID")x.linuxDistroId=X;else x.linuxDistroVersion=X}}}catch{}return x}),bR0=Q1(()=>{if(process.platform!=="darwin")return;let x=OP().match(/^(\d+)\./);if(!x||!x[1])return;return parseInt(x[1],10)-9}),bK0=Q1(function(){switch(BP()){case"macos":return"/Library/Application Support/ClaudeCode";case"windows":return"C:\\Program Files\\ClaudeCode";default:return"/etc/claude-code"}}),kR0=Q1(function(){return AK0(bK0(),"managed-settings.d")});xG=kK0;PK0=gK0,wK0=PK0(),uK0=wK0;yK0=fK0,mK0=Function.prototype,_K0=Object.prototype,vP=mK0.toString,nK0=_K0.hasOwnProperty,lK0=vP.call(Object);iK0=dK0;YG=pK0;oK0=sK0;tK0=rK0;eK0=MP;xV0=aK0,uc=Math.max;RP=YV0;QV0=ZV0,JV0=!DJ?OA:function(x,Z){return DJ(x,"toString",{configurable:!0,enumerable:!1,value:QV0(Z),writable:!0})},XV0=JV0,KV0=Date.now;HV0=VV0,GV0=HV0(XV0),SP=GV0;FV0=$V0;NV0=UV0;DV0=LV0,gR0=DV0(function(x,Z,Q,J){eK0(x,Z,Q,J)});BV0=OV0;MV0=vV0;SV0=RV0,fc=N6?N6.isConcatSpreadable:void 0;jV0=CV0;TV0=CP;cV0=IV0;AV0=qV0,PR0=AV0(function(x,Z){return x==null?{}:SV0(x,Z)}),EV0=W0(()=>R.object({allowedDomains:R.array(R.string()).optional(),deniedDomains:R.array(R.string()).optional().describe("Domains that are always blocked, even if matched by allowedDomains. Supports the same wildcard syntax as allowedDomains. Merged from all settings sources regardless of allowManagedDomainsOnly."),allowManagedDomainsOnly:R.boolean().optional().describe("When true (and set in managed settings), only allowedDomains and WebFetch(domain:...) allow rules from managed settings are respected. User, project, local, and flag settings domains are ignored. Denied domains are still respected from all sources."),allowUnixSockets:R.array(R.string()).optional().describe("macOS only: Unix socket paths to allow. Ignored on Linux (seccomp cannot filter by path)."),allowAllUnixSockets:R.boolean().optional().describe("If true, allow all Unix sockets (disables blocking on both platforms)."),allowLocalBinding:R.boolean().optional(),allowMachLookup:R.array(R.string().refine((x)=>!(x.endsWith("*")?x.slice(0,-1):x).includes("*"),{message:'Wildcards are only allowed as a single trailing "*" (e.g., "com.example.*" or "*" for all services).'})).optional().describe('macOS only: Additional XPC/Mach service names to allow looking up. Supports trailing-wildcard prefix matching (e.g., "com.apple.coresimulator.*"). Needed for tools that communicate via XPC such as the iOS Simulator or Playwright.'),httpProxyPort:R.number().optional(),socksProxyPort:R.number().optional(),tlsTerminate:R.object({caCertPath:R.string().min(1).optional(),caKeyPath:R.string().min(1).optional()}).optional().describe("[EXPERIMENTAL] Enable in-process TLS termination so the per-request filter can see HTTPS request bodies. Provide a CA cert+key, or omit both to have sandbox-runtime generate an ephemeral one for the session.")}).optional()),bV0=W0(()=>R.object({allowWrite:R.array(R.string()).optional().describe("Additional paths to allow writing within the sandbox. Merged with paths from Edit(...) allow permission rules."),denyWrite:R.array(R.string()).optional().describe("Additional paths to deny writing within the sandbox. Merged with paths from Edit(...) deny permission rules."),denyRead:R.array(R.string()).optional().describe("Additional paths to deny reading within the sandbox. Merged with paths from Read(...) deny permission rules."),allowRead:R.array(R.string()).optional().describe("Paths to re-allow reading within denyRead regions. Takes precedence over denyRead for matching paths."),allowManagedReadPathsOnly:R.boolean().optional().describe("When true (set in managed settings), only allowRead paths from policySettings are used.")}).optional()),kV0=W0(()=>R.object({enabled:R.boolean().optional(),failIfUnavailable:R.boolean().optional().describe("Exit with an error at startup if sandbox.enabled is true but the sandbox cannot start (missing dependencies or unsupported platform). When false (default), a warning is shown and commands run unsandboxed. Intended for managed-settings deployments that require sandboxing as a hard gate."),autoAllowBashIfSandboxed:R.boolean().optional(),allowUnsandboxedCommands:R.boolean().optional().describe("Allow commands to run outside the sandbox via the dangerouslyDisableSandbox parameter. When false, the dangerouslyDisableSandbox parameter is completely ignored and all commands must run sandboxed. Default: true."),network:EV0(),filesystem:bV0(),ignoreViolations:R.record(R.string(),R.array(R.string())).optional(),enableWeakerNestedSandbox:R.boolean().optional(),enableWeakerNetworkIsolation:R.boolean().optional().describe("macOS only: Allow access to com.apple.trustd.agent in the sandbox. Needed for Go-based CLI tools (gh, gcloud, terraform, etc.) to verify TLS certificates when using httpProxyPort with a MITM proxy and custom CA. "+"**Reduces security** — opens a potential data exfiltration vector through the trustd service. Default: false"),allowAppleEvents:R.boolean().optional().describe("macOS only: Allow sandboxed commands to send Apple Events (and look up the appleeventsd Mach service). Needed for `open`, `osascript`, and browser-based auth flows that open URLs. "+"**Removes code-execution isolation** — sandboxed commands can launch other applications "+"unsandboxed with no user prompt, and can script running apps (e.g. Terminal) subject to the user's per-app TCC automation consent. "+"Only honored from user, managed/policy, or CLI (--settings) settings — "+"project settings (.claude/settings.json and .claude/settings.local.json) are ignored. Default: false"),excludedCommands:R.array(R.string()).optional(),ripgrep:R.object({command:R.string(),args:R.array(R.string()).optional()}).optional().describe("Custom ripgrep configuration for bundled ripgrep support"),bwrapPath:R.preprocess((x)=>typeof x==="string"&&yc(x)?x:void 0,R.string()).optional().catch(void 0).describe("Linux/WSL only: Absolute path to the bwrap (bubblewrap) binary. Overrides auto-detection via PATH. Only honored from admin-controlled managed settings."),socatPath:R.preprocess((x)=>typeof x==="string"&&yc(x)?x:void 0,R.string()).optional().catch(void 0).describe("Linux/WSL only: Absolute path to the socat binary used for the sandbox network proxy. Overrides auto-detection via PATH. Only honored from admin-controlled managed settings.")}).passthrough()),gV0=["auto","iterm2","iterm2_with_bell","terminal_bell","kitty","ghostty","notifications_disabled"],PV0=["normal","vim"],wV0=["auto","tmux","in-process"],uV0=["dark","light","light-daltonized","dark-daltonized","light-ansi","dark-ansi"],fV0=["auto",...uV0],uR0=BP()==="macos"?"⏺":"●",KU=["acceptEdits","auto","bypassPermissions","default","dontAsk","plan"],yV0=[...KU,"bubble"],hV0=yV0,fR0=W0(()=>mg.enum(hV0)),yR0=W0(()=>mg.enum(KU)),mV0=["bash","powershell"],V2=W0(()=>R.string().optional().describe('Permission rule syntax to filter when this hook runs (e.g., "Bash(git *)"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.'));nV0=W0(()=>{let{BashCommandHookSchema:x,PromptHookSchema:Z,AgentHookSchema:Q,HttpHookSchema:J,McpToolHookSchema:X}=_V0();return R.discriminatedUnion("type",[x,Z,Q,J,X])}),lV0=W0(()=>R.object({matcher:R.string().optional().describe('String pattern to match (e.g. tool names like "Write")'),hooks:R.array(nV0()).describe("List of hooks to execute when the matcher matches")})),hJ=W0(()=>R.partialRecord(R.enum(vq),R.array(lV0()))),hR0=W0(()=>R.enum(["local","user","project","dynamic","enterprise","claudeai","managed","agent"])),mR0=W0(()=>R.enum(["stdio","sse","sse-ide","http","ws","sdk"])),N5=W0(()=>R.literal("comms").optional().catch(void 0)),B6=W0(()=>R.number().int().positive()),dV0=W0(()=>R.object({type:R.literal("stdio").optional(),command:R.string().min(1,"Command cannot be empty"),args:R.array(R.string()).default([]),env:R.record(R.string(),R.string()).optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5()})),iV0=W0(()=>R.boolean()),jP=W0(()=>R.object({clientId:R.string().optional(),callbackPort:R.number().int().positive().optional(),authServerMetadataUrl:R.string().url().startsWith("https://",{message:"authServerMetadataUrl must use https://"}).optional(),scopes:R.string().min(1).optional(),xaa:iV0().optional()})),pV0=W0(()=>R.object({type:R.literal("sse"),url:R.string(),headers:R.record(R.string(),R.string()).optional(),headersHelper:R.string().optional(),oauth:jP().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5(),toolPermissions:R.record(R.string(),VU()).optional()})),sV0=W0(()=>R.object({type:R.literal("sse-ide"),url:R.string(),ideName:R.string(),ideRunningInWindows:R.boolean().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5()})),oV0=W0(()=>R.object({type:R.literal("ws-ide"),url:R.string(),ideName:R.string(),authToken:R.string().optional(),ideRunningInWindows:R.boolean().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5()})),rV0=W0(()=>R.object({type:R.enum(["http","streamable-http"]).transform(()=>"http"),url:R.string(),headers:R.record(R.string(),R.string()).optional(),headersHelper:R.string().optional(),oauth:jP().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5(),toolPermissions:R.record(R.string(),VU()).optional()})),tV0=W0(()=>R.object({type:R.literal("ws"),url:R.string(),headers:R.record(R.string(),R.string()).optional(),headersHelper:R.string().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),role:N5()})),eV0=W0(()=>R.object({type:R.literal("sdk"),name:R.string(),timeout:B6().optional(),alwaysLoad:R.boolean().optional()})),VU=W0(()=>R.enum(["allow","ask","blocked"])),aV0=W0(()=>R.object({type:R.literal("claudeai-proxy"),url:R.string(),id:R.string(),displayName:R.string().optional(),iconUrl:R.string().optional(),timeout:B6().optional(),alwaysLoad:R.boolean().optional(),toolPermissions:R.record(R.string(),VU()).optional(),stateless:R.boolean().optional(),cachedInitResponse:R.record(R.string(),R.unknown()).nullish()})),ZG=W0(()=>R.union([dV0(),pV0(),sV0(),oV0(),rV0(),tV0(),eV0(),aV0()])),_R0=W0(()=>R.object({mcpServers:R.record(R.string(),ZG())})),xH0=new Set(["claude-community","claude-plugins-community"]),YH0=new Set(["claude-code-marketplace","claude-code-plugins","claude-plugins-official","anthropic-marketplace","anthropic-plugins","agent-skills","anthropic-agent-skills","life-sciences","knowledge-work-plugins","claude-for-legal","claude-for-financial-services","financial-services-plugins"]),TP=new Set([...YH0,...xH0]),ZH0=/(?:official[^a-z0-9]*(anthropic|claude)|(?:anthropic|claude)[^a-z0-9]*official|^(?:anthropic|claude)[^a-z0-9]*(marketplace|plugins|official))/i,QH0=/[^\u0020-\u007E]/;A8=W0(()=>R.string().startsWith("./")),D3=W0(()=>A8().endsWith(".json")),hc=W0(()=>R.union([A8().refine((x)=>x.endsWith(".mcpb")||x.endsWith(".dxt"),{message:"MCPB file path must end with .mcpb or .dxt"}).describe("Path to MCPB file relative to plugin root"),R.string().url().refine((x)=>x.endsWith(".mcpb")||x.endsWith(".dxt"),{message:"MCPB URL must end with .mcpb or .dxt"}).describe("URL to MCPB file")])),QG=W0(()=>A8().endsWith(".md")),JG=W0(()=>R.union([QG(),A8()])),IP=W0(()=>R.string().min(1,"Marketplace must have a name").refine((x)=>!x.includes(" "),{message:'Marketplace name cannot contain spaces. Use kebab-case (e.g., "my-marketplace")'}).refine((x)=>!x.includes("/")&&!x.includes("\\")&&!x.includes("..")&&x!==".",{message:'Marketplace name cannot contain path separators (/ or \\), ".." sequences, or be "."'}).refine((x)=>!JH0(x),{message:"Marketplace name impersonates an official Anthropic/Claude marketplace"}).refine((x)=>x.toLowerCase()!=="inline",{message:'Marketplace name "inline" is reserved for --plugin-dir session plugins'}).refine((x)=>x.toLowerCase()!=="builtin",{message:'Marketplace name "builtin" is reserved for built-in plugins'}).refine((x)=>x.toLowerCase()!=="skills-dir",{message:'Marketplace name "skills-dir" is reserved for plugins auto-loaded from .claude/skills/'})),HU=W0(()=>R.object({name:R.string().min(1,"Author name cannot be empty").describe("Display name of the plugin author or organization"),email:R.string().optional().describe("Contact email for support or feedback"),url:R.string().optional().describe("Website, GitHub profile, or organization URL")})),XH0=W0(()=>R.object({$schema:R.string().optional().describe("JSON Schema reference for editor autocomplete/validation; ignored at load time"),name:R.string().min(1,"Plugin name cannot be empty").refine((x)=>!x.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Unique identifier for the plugin, used for namespacing (prefer kebab-case)"),displayName:R.string().optional().describe('Human-readable name shown in UI (e.g., "GitHub Utils"). Falls back to `name` when omitted. Unlike `name`, may contain spaces and any casing; not used for namespacing or lookup.'),version:R.string().optional().describe("Semantic version (e.g., 1.2.3) following semver.org specification"),description:R.string().optional().describe("Brief, user-facing explanation of what the plugin provides"),author:HU().optional().describe("Information about the plugin creator or maintainer"),homepage:R.string().url().optional().describe("Plugin homepage or documentation URL"),repository:R.string().optional().describe("Source code repository URL"),license:R.string().optional().describe("SPDX license identifier (e.g., MIT, Apache-2.0)"),keywords:R.array(R.string()).optional().describe("Tags for plugin discovery and categorization"),defaultEnabled:R.boolean().optional().describe("Whether the plugin starts enabled when the user has no explicit enabled/disabled setting for it (default: true). Explicit enabledPlugins values always win, and a plugin required by an enabled dependent is enabled regardless of this value."),dependencies:R.array(qH0()).optional().describe(`Plugins that must be enabled for this plugin to function. Bare names (no "@marketplace") are resolved against the declaring plugin's own marketplace.`)})),nR0=W0(()=>R.object({description:R.string().optional().describe("Brief, user-facing explanation of what these hooks provide"),hooks:R.lazy(()=>hJ()).describe("The hooks provided by the plugin, in the same format as the one used for settings")})),zH0=W0(()=>R.object({hooks:R.union([D3().describe("Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root"),R.lazy(()=>hJ()).describe("Additional hooks (in addition to those in hooks/hooks.json, if it exists)"),R.array(R.union([D3().describe("Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root"),R.lazy(()=>hJ()).describe("Additional hooks (in addition to those in hooks/hooks.json, if it exists)")]))])})),WH0=W0(()=>R.object({source:JG().optional().describe("Path to command markdown file, relative to plugin root"),content:R.string().optional().describe("Inline markdown content for the command"),description:R.string().optional().describe("Command description override"),argumentHint:R.string().optional().describe('Hint for command arguments (e.g., "[file]")'),model:R.string().optional().describe("Default model for this command"),allowedTools:R.array(R.string()).optional().describe("Tools allowed when command runs")}).refine((x)=>x.source&&!x.content||!x.source&&x.content,{message:'Command must have either "source" (file path) or "content" (inline markdown), but not both'})),KH0=W0(()=>R.object({commands:R.union([JG().describe("Path to a command file or skill directory, relative to the plugin root. When set, the commands/ directory is not auto-loaded — list its files here if you want both."),R.array(JG().describe("Path to a command file or skill directory, relative to the plugin root. When set, the commands/ directory is not auto-loaded — list its files here if you want both.")).describe("List of command file or skill directory paths. When set, the commands/ directory is not auto-loaded."),R.record(R.string(),WH0()).describe('Object mapping of command names to their metadata and source files. Command name becomes the slash command name (e.g., "about" → "/plugin:about")')])})),VH0=W0(()=>R.object({agents:R.union([QG().describe("Path to an agent file, relative to the plugin root. When set, the agents/ directory is not auto-loaded — list its files here if you want both."),R.array(QG().describe("Path to an agent file, relative to the plugin root. When set, the agents/ directory is not auto-loaded — list its files here if you want both.")).describe("List of agent file paths. When set, the agents/ directory is not auto-loaded.")])})),HH0=W0(()=>R.object({skills:R.union([A8().describe("Path to a skill directory, relative to the plugin root. Loaded in addition to the skills/ directory (except: for a marketplace entry whose source resolves to the marketplace root, declaring a specific subdirectory replaces the skills/ scan)."),R.array(A8().describe("Path to a skill directory, relative to the plugin root.")).describe("List of skill directory paths, loaded in addition to the skills/ directory (except: for a marketplace entry whose source resolves to the marketplace root, declaring specific subdirectories replaces the skills/ scan).")])})),cP=W0(()=>R.object({outputStyles:R.union([A8().describe("Path to an output-styles directory or file, relative to the plugin root. When set, the output-styles/ directory is not auto-loaded — list its files here if you want both."),R.array(A8().describe("Path to an output-styles directory or file, relative to the plugin root. When set, the output-styles/ directory is not auto-loaded — list its files here if you want both.")).describe("List of output-style directory or file paths. When set, the output-styles/ directory is not auto-loaded.")])})),qP=W0(()=>R.object({themes:R.union([A8().describe("Path to a themes directory or file, relative to the plugin root. When set, the themes/ directory is not auto-loaded — list its files here if you want both."),R.array(A8().describe("Path to a themes directory or file, relative to the plugin root. When set, the themes/ directory is not auto-loaded — list its files here if you want both.")).describe("List of theme directory or file paths. When set, the themes/ directory is not auto-loaded.")])})),GH0=W0(()=>R.object({})),mc=W0(()=>R.string().min(1)),$H0=W0(()=>R.string().min(2).refine((x)=>x.startsWith("."),{message:'File extensions must start with dot (e.g., ".ts", not "ts")'})),FH0=W0(()=>R.object({mcpServers:R.union([D3().describe("MCP servers to include in the plugin (in addition to those in the .mcp.json file, if it exists)"),hc().describe("Path or URL to MCPB file containing MCP server configuration"),R.record(R.string(),ZG()).describe("MCP server configurations keyed by server name"),R.array(R.union([D3().describe("Path to MCP servers configuration file"),hc().describe("Path or URL to MCPB file"),R.record(R.string(),ZG()).describe("Inline MCP server configurations")])).describe("Array of MCP server configurations (paths, MCPB files, or inline definitions)")])})),AP=W0(()=>R.object({type:R.enum(["string","number","boolean","directory","file"]).describe("Type of the configuration value"),title:R.string().describe("Human-readable label shown in the config dialog"),description:R.string().describe("Help text shown beneath the field in the config dialog"),required:R.boolean().optional().describe("If true, validation fails when this field is empty"),default:R.union([R.string(),R.number(),R.boolean(),R.array(R.string())]).optional().describe("Default value used when the user provides nothing"),multiple:R.boolean().optional().describe("For string type: allow an array of strings"),sensitive:R.boolean().optional().describe("If true, masks dialog input and stores value in secure storage (keychain/credentials file) instead of settings.json"),min:R.number().optional().describe("Minimum value (number type only)"),max:R.number().optional().describe("Maximum value (number type only)")}).strict()),UH0=W0(()=>R.object({userConfig:R.record(R.string().regex(/^[A-Za-z_]\w*$/,"Option keys must be valid identifiers (letters, digits, underscore; no leading digit) — they become CLAUDE_PLUGIN_OPTION_<KEY> env vars in hooks"),AP()).optional().describe("User-configurable values this plugin needs. Prompted at enable time. Non-sensitive values saved to settings.json; sensitive values to secure storage. Available as ${user_config.KEY} in MCP/LSP server config, hook commands, and (non-sensitive only) skill/agent content. Keep sensitive value counts small.")})),NH0=W0(()=>R.object({channels:R.array(R.object({server:R.string().min(1).describe("Name of the MCP server this channel binds to. Must match a key in this plugin's mcpServers."),displayName:R.string().optional().describe('Human-readable name shown in the config dialog title (e.g., "Telegram"). Defaults to the server name.'),userConfig:R.record(R.string(),AP()).optional().describe("Fields to prompt the user for when enabling this plugin in assistant mode. Saved values are substituted into ${user_config.KEY} references in the mcpServers env.")}).strict()).describe("Channels this plugin provides. Each entry declares an MCP server as a message channel and optionally specifies user configuration to prompt for at enable time.")})),_c=W0(()=>R.strictObject({command:R.string().min(1).refine((x)=>{if(x.includes(" ")&&!x.startsWith("/"))return!1;return!0},{message:"Command should not contain spaces. Use args array for arguments."}).describe('Command to execute the LSP server (e.g., "typescript-language-server")'),args:R.array(mc()).optional().describe("Command-line arguments to pass to the server"),extensionToLanguage:R.record($H0(),mc()).refine((x)=>Object.keys(x).length>0,{message:"extensionToLanguage must have at least one mapping"}).describe("Mapping from file extension to LSP language ID. File extensions and languages are derived from this mapping."),transport:R.enum(["stdio","socket"]).default("stdio").describe("Communication transport mechanism"),env:R.record(R.string(),R.string()).optional().describe("Environment variables to set when starting the server"),initializationOptions:R.unknown().optional().describe("Initialization options passed to the server during initialization"),settings:R.unknown().optional().describe("Settings passed to the server via workspace/didChangeConfiguration"),workspaceFolder:R.string().optional().describe("Workspace folder path to use for the server"),startupTimeout:R.number().int().positive().optional().describe("Maximum time to wait for server startup (milliseconds)"),shutdownTimeout:R.number().int().positive().optional().describe("Maximum time to wait for graceful shutdown (milliseconds)"),restartOnCrash:R.boolean().optional().describe("Whether to restart the server if it crashes"),maxRestarts:R.number().int().nonnegative().optional().describe("Maximum number of restart attempts before giving up"),diagnostics:R.boolean().optional().describe("Whether to push publishDiagnostics into the agent context after edits. Set to false to keep LSP navigation (goToDefinition, hover, etc.) but suppress automatic diagnostic injection. Defaults to true.")})),LH0=W0(()=>R.strictObject({name:R.string().min(1).describe("Identifier for this monitor, unique within the plugin. Used to dedupe so re-arming (plugin reload, repeat skill invoke) does not spawn duplicates."),command:R.string().min(1).describe('Shell command to run as a persistent background monitor. Each stdout line is delivered to the model as a <task_notification> event; the process runs for the session lifetime. ${CLAUDE_PLUGIN_ROOT}, ${CLAUDE_PLUGIN_DATA}, ${CLAUDE_PROJECT_DIR}, ${user_config.*}, and ${ENV_VAR} are substituted. Runs in the session cwd — prefix with `cd "${CLAUDE_PLUGIN_ROOT}" && ` if the script needs its own directory.'),description:R.string().min(1).describe("Short human-readable description of what is being monitored (shown in task panel and notification summary)."),when:R.union([R.literal("always"),R.string().startsWith("on-skill-invoke:").refine((x)=>x.length>16,{message:"on-skill-invoke: must specify a skill name"})]).default("always").describe('Arm trigger. "always" arms at session start and on plugin reload. "on-skill-invoke:<skill>" arms the first time that skill is dispatched (via Skill tool or slash command).')})),DH0=W0(()=>R.array(LH0()).refine((x)=>new Set(x.map((Z)=>Z.name)).size===x.length,{message:"Monitor names must be unique within a plugin"})),EP=W0(()=>R.object({monitors:R.union([D3().describe("Path to a JSON file containing the monitors array, relative to the plugin root"),DH0()]).describe("Background watch scripts the host arms as persistent Monitor tasks (unsandboxed, same trust tier as hooks) so plugins need not instruct the model to arm them. When omitted, monitors/monitors.json at the plugin root is loaded if present.")})),OH0=W0(()=>R.object({lspServers:R.union([D3().describe("Path to .lsp.json configuration file relative to plugin root"),R.record(R.string(),_c()).describe("LSP server configurations keyed by server name"),R.array(R.union([D3().describe("Path to LSP configuration file"),R.record(R.string(),_c()).describe("Inline LSP server configurations")])).describe("Array of LSP server configurations (paths or inline definitions)")])})),bP=W0(()=>R.string().refine((x)=>!x.includes("..")&&!x.includes("//"),"Package name cannot contain path traversal patterns").refine((x)=>{let Z=/^@[a-z0-9][a-z0-9-._]*\/[a-z0-9][a-z0-9-._]*$/,Q=/^[a-z0-9][a-z0-9-._]*$/;return Z.test(x)||Q.test(x)},"Invalid npm package name format")),BH0=W0(()=>R.object({settings:R.record(R.string(),R.unknown()).optional().describe("Settings to merge into the user settings while this plugin is enabled. Only the documented allowlisted keys are applied.")})),vH0=W0(()=>R.object({experimental:R.preprocess((x)=>typeof x==="object"&&x!==null&&!Array.isArray(x)?x:void 0,R.object({...qP().partial().shape,...EP().partial().shape,...cP().partial().shape,evals:R.union([R.string(),R.array(R.string())]).optional().describe("Path(s) to evaluation query files for `claude plugin eval`. Defaults to `evals/`.")}).optional().describe("Components whose manifest shape may change without a deprecation cycle. Move a key out of here once it is promoted to stable."))})),MH0=W0(()=>R.object({...XH0().shape,...zH0().partial().shape,...KH0().partial().shape,...VH0().partial().shape,...HH0().partial().shape,...cP().partial().shape,...qP().partial().shape,...GH0().shape,...NH0().partial().shape,...FH0().partial().shape,...OH0().partial().shape,...EP().partial().shape,...BH0().partial().shape,...UH0().partial().shape,...vH0().partial().shape})),mJ=W0(()=>R.discriminatedUnion("source",[R.object({source:R.literal("url"),url:R.string().url().describe("Direct URL to marketplace.json file"),headers:R.record(R.string(),R.string()).optional().describe("Custom HTTP headers (e.g., for authentication)")}),R.object({source:R.literal("github"),repo:R.string().describe("GitHub repository in owner/repo format"),ref:R.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),path:R.string().optional().describe("Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"),sparsePaths:R.array(R.string()).optional().describe('Directories to include via git sparse-checkout (cone mode). Use for monorepos where the marketplace lives in a subdirectory. Example: [".claude-plugin", "plugins"]. If omitted, the full repository is cloned.'),skipLfs:R.boolean().optional().describe("Skip Git LFS smudge during clone and update (sets GIT_LFS_SKIP_SMUDGE=1) so LFS pointer files stay as pointers instead of downloading their content. Use for marketplaces hosted in repos with large LFS objects.")}),R.object({source:R.literal("git"),url:R.string().describe("Full git repository URL"),ref:R.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),path:R.string().optional().describe("Path to marketplace.json within repo (defaults to .claude-plugin/marketplace.json)"),sparsePaths:R.array(R.string()).optional().describe('Directories to include via git sparse-checkout (cone mode). Use for monorepos where the marketplace lives in a subdirectory. Example: [".claude-plugin", "plugins"]. If omitted, the full repository is cloned.'),skipLfs:R.boolean().optional().describe("Skip Git LFS smudge during clone and update (sets GIT_LFS_SKIP_SMUDGE=1) so LFS pointer files stay as pointers instead of downloading their content. Use for marketplaces hosted in repos with large LFS objects.")}),R.object({source:R.literal("npm"),package:bP().describe("NPM package containing marketplace.json")}),R.object({source:R.literal("file"),path:R.string().describe("Local file path to marketplace.json")}),R.object({source:R.literal("directory"),path:R.string().describe("Local directory containing .claude-plugin/marketplace.json")}),R.object({source:R.literal("skills-dir")}).describe("Policy-list sentinel for the ~/.claude/skills/ auto-load (@skills-dir plugins). In strictKnownMarketplaces: opt the scan back IN (by default any allowlist blocks it). In blockedMarketplaces: turn the scan OFF without otherwise restricting marketplaces. Only meaningful in those two managed-settings lists (areLocalPluginDirsAllowedByPolicy); known_marketplaces.json / marketplace add etc. ignore it."),R.object({source:R.literal("hostPattern"),hostPattern:R.string().describe('Regex pattern to match the host/domain extracted from any marketplace source type. For github sources, matches against "github.com". For git sources (SSH or HTTPS), extracts the hostname from the URL. Use in strictKnownMarketplaces to allow all marketplaces from a specific host (e.g., "^github\\.mycompany\\.com$").')}),R.object({source:R.literal("pathPattern"),pathPattern:R.string().describe('Regex pattern matched against the .path field of file and directory sources. Use in strictKnownMarketplaces to allow filesystem-based marketplaces alongside hostPattern restrictions for network sources. Use ".*" to allow all filesystem paths, or a narrower pattern (e.g., "^/opt/approved/") to restrict to specific directories.')}),R.object({source:R.literal("settings"),name:IP().refine((x)=>!TP.has(x.toLowerCase()),{message:"Reserved marketplace names cannot be used with settings sources. validateOfficialNameSource only accepts github/git sources from anthropics/* for these names; a settings source would be rejected after loadAndCacheMarketplace has already written to disk with cleanupNeeded=false."}).describe("Marketplace name. Must match the extraKnownMarketplaces key (enforced); the synthetic manifest is written under this name. Same validation "+"as PluginMarketplaceSchema plus reserved-name rejection — "+"validateOfficialNameSource runs after the disk write, too late to clean up."),plugins:R.array(RH0()).describe("Plugin entries declared inline in settings.json"),owner:HU().optional()}).describe("Inline marketplace manifest defined directly in settings.json. The reconciler writes a synthetic marketplace.json to the cache; diffMarketplaces detects edits via isEqual on the stored source (the plugins array is inside this object, so edits surface as sourceChanged).")])),cH=W0(()=>R.string().length(40).regex(/^[a-f0-9]{40}$/,"Must be a full 40-character lowercase git commit SHA")),kP=W0(()=>R.union([R.preprocess((x)=>x==="."?"./":x,A8()).describe("Path to the plugin root, relative to the marketplace root (the directory containing .claude-plugin/, not .claude-plugin/ itself)"),R.object({source:R.literal("npm"),package:bP().or(R.string().refine((x)=>/^(?:file|https?|git(?:\+https?|\+ssh)?|ssh|github|gitlab|bitbucket):/i.test(x)||!x.includes(".."),'Package reference cannot contain ".." path segments')).describe("Package name (or url, or local path, or anything else that can be passed to `npm` as a package)"),version:R.string().optional().describe("Specific version or version range (e.g., ^1.0.0, ~2.1.0)"),registry:R.string().url().optional().describe("Custom NPM registry URL (defaults to using system default, likely npmjs.org)")}).describe("NPM package as plugin source"),R.object({source:R.literal("url"),url:R.string().describe("Full git repository URL (https:// or git@)"),ref:R.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:cH().optional().describe("Specific commit SHA to use")}),R.object({source:R.literal("github"),repo:R.string().describe("GitHub repository in owner/repo format"),ref:R.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:cH().optional().describe("Specific commit SHA to use")}),R.object({source:R.literal("git-subdir"),url:R.string().describe("Git repository: GitHub owner/repo shorthand, https://, or git@ URL"),path:R.string().min(1).describe('Subdirectory within the repo containing the plugin (e.g., "tools/claude-plugin"). Cloned sparsely using partial clone (--filter=tree:0) to minimize bandwidth for monorepos.'),ref:R.string().optional().describe('Git branch or tag to use (e.g., "main", "v1.0.0"). Defaults to repository default branch.'),sha:cH().optional().describe("Specific commit SHA to use")}).describe("Plugin located in a subdirectory of a larger repository (monorepo). Only the specified subdirectory is materialized; the rest of the repo is not downloaded."),R.object({source:R.literal("unsupported")}).describe("Placeholder for source types this Claude Code version does not "+"recognize. Never authored by hand — PluginMarketplaceSchema rewrites "+'unparseable sources to this so the entry remains in marketplace.plugins (detectDelistedPlugins must not see it as removed). Install attempts fail at cachePlugin with a clear "update Claude Code" message.')])),RH0=W0(()=>R.object({name:R.string().min(1,"Plugin name cannot be empty").refine((x)=>!x.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Plugin name as it appears in the target repository"),source:kP().describe("Where to fetch the plugin from. Must be a remote source — relative "+"paths have no marketplace repository to resolve against."),description:R.string().optional(),version:R.string().optional(),strict:R.boolean().optional()}).refine((x)=>typeof x.source!=="string",{message:'Plugins in a settings-sourced marketplace must use remote sources (github, git-subdir, npm, url). Relative-path sources like "./foo" have no marketplace repository to resolve against.'}).refine((x)=>typeof x.source==="string"||x.source.source!=="unsupported",{message:"source.source: 'unsupported' is a parse-time placeholder and cannot be authored. Use a remote source (github, git-subdir, npm, url)."})),SH0=W0(()=>R.object({cli:R.array(R.string().max(64)).max(10).optional().describe('First command tokens (e.g. ["stripe"]) — exact match against commands run this session.'),hosts:R.array(R.string().max(128)).max(20).optional().describe('Hostnames (e.g. ["api.stripe.com"]) — exact, case-insensitive match against '+"hostnames seen in https?:// URLs in bash commands run this session. Bare hostname only: lowercase, no scheme, no port, no path."),filesRead:R.array(R.string().max(256)).max(10).optional().describe('Glob patterns (e.g. ["**/*.tf"]) — the plugin is relevant when a file Claude has read '+"this session matches any pattern. Matched against read-file paths, forward-slash normalized, case-insensitive."),manifestDeps:R.array(R.object({file:R.string().max(256),pattern:R.string().max(256)})).max(10).optional().describe("Dependency declared in a package manifest. Each {file, pattern} is a pair of RegExp sources: "+"`file` matches the manifest filename (package.json, go.mod, requirements.txt, …); "+"`pattern` matches the dependency declaration inside that file. Evaluated against files read this session."),cwd:R.array(R.string().max(256)).max(10).optional().describe('Glob patterns (e.g. ["Engine/Source/Runtime/Renderer/**"]) — the plugin is relevant when the '+`session's working directory is at or under a directory matching the pattern. Matched against the cwd both relative to the enclosing git repo root and as an absolute path, forward-slash normalized, case-insensitive. A bare directory (no glob characters) means "cwd is at or under this directory". Known at session start, so this signal can surface a suggestion before the first turn.`)})),CH0=W0(()=>R.object({topic:R.string().max(64).optional().describe('What the user is working with when this plugin is relevant — fills "Working with {topic}?". '+'Often the product name (e.g. "Stripe"); use a domain (e.g. "design") when the plugin name does not read naturally as a topic. Defaults to the plugin name with each hyphen-segment capitalized.'),signals:SH0().optional().describe("Matchers that determine when the plugin is relevant.")})),jH0=W0(()=>MH0().partial().extend({name:R.string().min(1,"Plugin name cannot be empty").refine((x)=>!x.includes(" "),{message:'Plugin name cannot contain spaces. Use kebab-case (e.g., "my-plugin")'}).describe("Unique identifier matching the plugin name"),source:kP().describe("Where to fetch the plugin from"),category:R.string().optional().describe('Category for organizing plugins (e.g., "productivity", "development")'),tags:R.array(R.string()).optional().describe("Tags for searchability and discovery"),strict:R.boolean().optional().default(!0).describe("Require the plugin manifest to be present in the plugin folder. If false, the marketplace entry provides the manifest."),relevance:R.preprocess((x)=>typeof x==="object"&&x!==null&&!Array.isArray(x)?x:void 0,CH0().optional()).describe(`Declares when this plugin is relevant to the user's work. Consumed by the spinner tip ("Working with {topic}?"), session-start auto-suggest, and marketplace browse ranking.`)})),TH0=W0(()=>R.object({name:R.string().min(1).refine((x)=>!x.includes(" "))}));lR0=W0(()=>R.object({$schema:R.string().optional().describe("JSON Schema reference for editor autocomplete/validation; ignored at load time"),name:IP(),version:R.string().optional().describe("Marketplace manifest version"),description:R.string().optional().describe("Human-readable description of this marketplace"),owner:HU().describe("Marketplace maintainer or curator information"),plugins:R.array(R.unknown()).transform(IH0).describe("Collection of available plugins in this marketplace"),forceRemoveDeletedPlugins:R.boolean().optional().describe("When true, plugins removed from this marketplace will be automatically uninstalled and flagged for users"),metadata:R.object({pluginRoot:R.string().optional().describe("Base path for relative plugin sources"),version:R.string().optional().describe("Marketplace version"),description:R.string().optional().describe("Marketplace description")}).optional().describe("Optional marketplace metadata"),allowCrossMarketplaceDependenciesOn:R.array(R.string()).optional().describe("Marketplace names whose plugins may be auto-installed as dependencies. Only the root marketplace's allowlist applies — no transitive trust.")})),gP=W0(()=>R.string().regex(/^[A-Za-z0-9][-A-Za-z0-9._]*@[A-Za-z0-9][-A-Za-z0-9._]*$/,"Plugin ID must be in format: plugin@marketplace")),cH0=/^[A-Za-z0-9][-A-Za-z0-9._]*(@[A-Za-z0-9][-A-Za-z0-9._]*)?(@\^[^@]*)?$/,qH0=W0(()=>R.union([R.string().regex(cH0,"Dependency must be a plugin name, optionally qualified with @marketplace").transform((x)=>x.replace(/@\^[^@]*$/,"")),R.object({name:R.string().min(1).regex(/^[A-Za-z0-9][-A-Za-z0-9._]*$/),marketplace:R.string().min(1).regex(/^[A-Za-z0-9][-A-Za-z0-9._]*$/).optional()}).loose().transform((x)=>x.marketplace?`${x.name}@${x.marketplace}`:x.name)])),AH0=W0(()=>R.object({version:R.string().describe("Currently installed version"),installedAt:R.string().describe("ISO 8601 timestamp of installation"),lastUpdated:R.string().optional().describe("ISO 8601 timestamp of last update"),installPath:R.string().describe("Absolute path to the installed plugin directory"),gitCommitSha:R.string().optional().describe("Git commit SHA for git-based plugins (for version tracking)"),resolvedVersion:R.string().optional().describe("Tag-derived semver this install resolved to (when fetched via a version constraint). Used by verifyAndDemote in preference to manifest.version, since the upstream may have forgotten to bump plugin.json."),auto:R.boolean().optional().describe("True when this plugin was pulled in as a dependency rather than installed explicitly. Auto-installed plugins are eligible for removal by the orphan sweep when nothing depends on them. Absent = manual (preserves pre-flag installs).")})),EH0=W0(()=>R.object({version:R.literal(1).describe("Schema version 1"),plugins:R.record(gP(),AH0()).describe("Map of plugin IDs to their installation metadata")})),bH0=W0(()=>R.enum(["managed","user","project","local"])),kH0=W0(()=>R.object({scope:bH0().describe("Installation scope"),projectPath:R.string().optional().describe("Project path (required for project/local scopes)"),installPath:R.string().describe("Absolute path to the versioned plugin directory"),version:R.string().optional().describe("Currently installed version"),installedAt:R.string().optional().describe("ISO 8601 timestamp of installation"),lastUpdated:R.string().optional().describe("ISO 8601 timestamp of last update"),gitCommitSha:R.string().optional().describe("Git commit SHA for git-based plugins"),resolvedVersion:R.string().optional().describe("Tag-derived semver this install resolved to"),auto:R.boolean().optional().describe("True when pulled in as a dependency. Eligible for orphan sweep.")})),gH0=W0(()=>R.object({version:R.literal(2).describe("Schema version 2"),plugins:R.record(gP(),R.array(kH0())).describe("Map of plugin IDs to arrays of installation entries")})),dR0=W0(()=>R.union([EH0(),gH0()])),PH0=W0(()=>R.object({source:mJ().describe("Where to fetch the marketplace from"),installLocation:R.string().describe("Local cache path where marketplace manifest is stored"),lastUpdated:R.string().describe("ISO 8601 timestamp of last marketplace refresh"),autoUpdate:R.boolean().optional().describe("Whether to automatically update this marketplace and its installed plugins on startup")})),iR0=W0(()=>R.record(R.string(),PH0())),wH0=["autoMode","deepLink","voice","briefView","screenReader"],XJ={},bX={autoMode:{buildGate:()=>!1,shape:()=>XJ,permissionsShape:()=>XJ,permissionModes:()=>[]},deepLink:{buildGate:()=>!0,shape:()=>({disableDeepLinkRegistration:R.enum(["disable"]).optional().describe("Prevent claude-cli:// protocol handler registration with the OS")})},voice:{buildGate:()=>!1,shape:()=>XJ},briefView:{buildGate:()=>!0,shape:()=>({defaultView:R.enum(["chat","transcript"]).optional().describe("Default transcript view: chat (SendUserMessage checkpoints only) or transcript (full)")})},screenReader:{buildGate:()=>!1,shape:()=>XJ}};nc={Task:"Agent",KillShell:"TaskStop",KillBash:"TaskStop",AgentOutputTool:"TaskOutput",BashOutputTool:"TaskOutput",AgentOutput:"TaskOutput",BashOutput:"TaskOutput",ListPeers:"ListAgents",Brief:"SendUserMessage",ListMcpResources:"ListMcpResourcesTool",ReadMcpResource:"ReadMcpResourceTool"};pR0=`mcp__${uP}__bash`,sR0=`mcp__${uP}__web_fetch`;_J={filePatternTools:["Read","Write","Edit","Glob","NotebookRead","NotebookEdit","Cd"],bashPrefixTools:["Bash"],customValidation:{WebSearch:(x)=>{if(x.includes("*")||x.includes("?"))return{valid:!1,error:"WebSearch does not support wildcards",suggestion:"Use exact search terms without * or ?",examples:["WebSearch(claude ai)","WebSearch(typescript tutorial)"]};return{valid:!0}},WebFetch:(x)=>{if(x.includes("://")||x.startsWith("http"))return{valid:!1,error:"WebFetch permissions use domain format, not URLs",suggestion:'Use "domain:hostname" format',examples:["WebFetch(domain:example.com)","WebFetch(domain:github.com)"]};if(!x.startsWith("domain:"))return{valid:!1,error:'WebFetch permissions must use "domain:" prefix',suggestion:'Use "domain:hostname" format',examples:["WebFetch(domain:example.com)","WebFetch(domain:*.google.com)"]};return{valid:!0}}}};ic=W0(()=>yP()),oH0=W0(()=>yP("allow"));rH0=W0(()=>R.record(R.string(),R.coerce.string()));oR0=W0(()=>hP(PP())),tH0=W0(()=>R.object({source:mJ().describe("Where to fetch the marketplace from"),installLocation:R.string().optional().describe("Local cache path where marketplace manifest is stored (auto-generated if not provided)"),autoUpdate:R.boolean().optional().describe("Whether to automatically update this marketplace and its installed plugins on startup")})),eH0=W0(()=>R.object({serverName:R.string().regex(/^[a-zA-Z0-9_-]+$/,"Server name can only contain letters, numbers, hyphens, and underscores").optional().describe("Name of the MCP server that users are allowed to configure"),serverCommand:R.array(R.string()).min(1,"Server command must have at least one element (the command)").optional().describe("Command array [command, ...args] to match exactly for allowed stdio servers"),serverUrl:R.string().optional().describe('URL pattern with wildcard support (e.g., "https://*.example.com/*") for allowed remote MCP servers')}).refine((x)=>fA([x.serverName!==void 0,x.serverCommand!==void 0,x.serverUrl!==void 0],Boolean)===1,{message:'Entry must have exactly one of "serverName", "serverCommand", or "serverUrl"'})),aH0=W0(()=>R.object({serverName:R.string().regex(/^[a-zA-Z0-9_-]+$/,"Server name can only contain letters, numbers, hyphens, and underscores").optional().describe("Name of the MCP server that is explicitly blocked"),serverCommand:R.array(R.string()).min(1,"Server command must have at least one element (the command)").optional().describe("Command array [command, ...args] to match exactly for blocked stdio servers"),serverUrl:R.string().optional().describe('URL pattern with wildcard support (e.g., "https://*.example.com/*") for blocked remote MCP servers')}).refine((x)=>fA([x.serverName!==void 0,x.serverCommand!==void 0,x.serverUrl!==void 0],Boolean)===1,{message:'Entry must have exactly one of "serverName", "serverCommand", or "serverUrl"'})),xG0=W0(()=>R.object({path:R.string().describe("Absolute path to the helper executable"),timeoutMs:R.number().int().min(1000).optional(),refreshIntervalMs:R.union([R.literal(0),R.number().int().min(60000)]).optional()})),pc=["skills","agents","hooks","mcp"],sc=Object.freeze({type:"invalid-entry-stripped"}),YG0=W0(()=>R.union([R.object({type:R.literal("regex").describe('Config variant. This client understands "regex": matches turn output and builds a URL from named capture groups. Entries with other variants are preserved but skipped at runtime.'),pattern:R.string().describe("Regex matched against turn output (tool results and assistant text)"),url:R.string().describe("Link target. {name} placeholders are filled from named regex capture groups, e.g. (?<id>...) -> {id}. Values are URL-encoded; the origin must be literal in the template. The scheme must be https, http, or a recognized editor or workspace deep-link scheme: vscode, vscode-insiders, cursor, windsurf, zed, jetbrains, idea, slack, linear, notion, figma."),label:R.string().optional().describe("Badge text. {name} placeholders filled from named capture groups; defaults to the full match.")}).passthrough(),R.object({type:R.string().describe("Config variant discriminator for entries this client does not understand; the entry is preserved as-is and skipped at runtime.")}).passthrough()]));QG0=W0(()=>ZG0(PP())),rR0=Object.freeze({serverName:"invalid-entry-stripped"}),tR0=[{matches:(x)=>x.path==="permissions.defaultMode"&&x.code==="invalid_value",tip:{suggestion:'Valid modes: "acceptEdits" (ask before file changes), "plan" (analysis only), "bypassPermissions" (auto-accept all), or "default" (standard behavior)',docLink:`${A4}/iam#permission-modes`}},{matches:(x)=>x.path==="apiKeyHelper"&&x.code==="invalid_type",tip:{suggestion:'Provide a shell command that outputs your API key to stdout. The script should output only the API key. Example: "/bin/generate_temp_api_key.sh"'}},{matches:(x)=>x.path==="cleanupPeriodDays"&&x.code==="too_small",tip:{suggestion:'cleanupPeriodDays must be at least 1. To keep transcripts for a long time, set a large number (e.g. 3650 for ~10 years). To disable transcript writes entirely, remove this setting and use the --no-session-persistence CLI flag or the SDK persistSession:false option instead. (0 is rejected because it previously silently disabled all transcript writes, which users setting it to mean "never clean up" did not expect.)'}},{matches:(x)=>x.path.startsWith("env.")&&x.code==="invalid_type",tip:{suggestion:'Environment variables must be strings. Wrap numbers and booleans in quotes. Example: "DEBUG": "true", "PORT": "3000"',docLink:`${A4}/settings#environment-variables`}},{matches:(x)=>(x.path==="permissions.allow"||x.path==="permissions.deny")&&x.code==="invalid_type"&&x.expected==="array",tip:{suggestion:'Permission rules must be in an array. Format: ["Tool(specifier)"]. Examples: ["Bash(npm run build)", "Edit(docs/**)", "Read(~/.zshrc)"]. Use * for wildcards.'}},{matches:(x)=>x.path.startsWith("hooks.")&&x.code==="invalid_key",tip:{suggestion:"Not a recognized hook event. Common events: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd, Stop. Check spelling and capitalization.",docLink:`${A4}/hooks`}},{matches:(x)=>/\.hooks\.\d+\.command$/.test(x.path)&&x.code==="invalid_type"&&x.received==="undefined",tip:{suggestion:'Command hooks require `command`. For exec form (no shell), set `command` to the executable and `args` to its arguments: {"type": "command", "command": "echo", "args": ["hi"]}. For shell form, set `command` to the full shell string: {"type": "command", "command": "echo hi"}.',docLink:`${A4}/hooks#exec-form-and-shell-form`}},{matches:(x)=>x.path.includes("hooks")&&x.code==="invalid_type",tip:{suggestion:'Hooks use a matcher + hooks array. The matcher is a string: a tool name ("Bash"), pipe-separated list ("Edit|Write"), or empty to match all. Example: {"PostToolUse": [{"matcher": "Edit|Write", "hooks": [{"type": "command", "command": "echo Done"}]}]}'}},{matches:(x)=>x.code==="invalid_type"&&x.expected==="boolean",tip:{suggestion:'Use true or false without quotes. Example: "includeCoAuthoredBy": true'}},{matches:(x)=>x.code==="unrecognized_keys",tip:{suggestion:"Check for typos or refer to the documentation for valid fields",docLink:`${A4}/settings`}},{matches:(x)=>x.code==="invalid_value"&&x.enumValues!==void 0,tip:{suggestion:void 0}},{matches:(x)=>x.code==="invalid_type"&&x.expected==="object"&&x.received===null&&x.path==="",tip:{suggestion:"Check for missing commas, unmatched brackets, or trailing commas. Use a JSON validator to identify the exact syntax error."}},{matches:(x)=>x.path==="permissions.additionalDirectories"&&x.code==="invalid_type",tip:{suggestion:'Must be an array of directory paths. Example: ["~/projects", "/tmp/workspace"]. You can also use --add-dir flag or /add-dir command',docLink:`${A4}/iam#working-directories`}}],eR0={permissions:`${A4}/iam#configuring-permissions`,env:`${A4}/settings#environment-variables`,hooks:`${A4}/hooks`},aR0=W0(()=>QG0().strict()),xS0=new Set(vq),YS0=Object.freeze({settings:{},errors:[]});process.env.NoDefaultCurrentDirectoryInExePath="1";KG0=new Set(["EBUSY","EMFILE","ENFILE","ENOTEMPTY","EPERM"])});function $G0(x){return{...dP[x]??{},..._x.claude.models[x]??{}}}function FG0(x){let Z=$G0(x);return{key:`claude:${x}`,name:x,displayName:Z.display_name?.trim()||`Claude Code · ${x}`,description:Z.description?.trim()||`使用 ${x} 路由运行 Claude Code 后端。`,sdkModel:Z.model?.trim()||"opus"}}function UG0(){return[...new Set([...Object.keys(dP),...Object.keys(_x.claude.models)])].map(FG0).filter((Z)=>Z!==null)}function NG0(x){if(!x?.startsWith("claude:"))return null;let Z=x.slice(7);if(!Z||Z==="default")return null;return UG0().find((Q)=>Q.name===Z||Q.key===x)??null}function v6(x){return x.startsWith("claude:")?x:`claude:${x}`}function GU(x){if(!x)return"opus";let Z=NG0(x);if(Z)return Z.sdkModel;let Q=x.startsWith("claude:")?x.slice(7):x;return Q==="default"?"opus":Q}var dP;var iP=E0(()=>{Z3();dP={glm:{display_name:"Claude Code · GLM",description:"使用 GLM 路由,适合中文交流和通用编码任务。"}}});import{existsSync as NU,readFileSync as eP}from"node:fs";import{homedir as zY}from"node:os";import{spawn as LG0}from"node:child_process";import{delimiter as pP,join as M3,posix as DG0,win32 as OG0}from"node:path";import{EventEmitter as BG0}from"node:events";function vG0(x){return x==="win32"?";":":"}function FU(x,...Z){return x==="win32"?OG0.join(...Z):DG0.join(...Z)}function sP(x){let Z=x.toLowerCase();return Z.endsWith(".cmd")||Z.endsWith(".bat")}function oP(x){let Z=LG0(x.command,x.args,{cwd:x.cwd,env:x.env,shell:!0,signal:x.signal,stdio:["pipe","pipe","ignore"],windowsHide:!0});if(!Z.stdin||!Z.stdout)throw Z.kill(),Error("failed to open stdio for Claude Code Windows shell shim");return Z}function xw(x={}){let Z=x.platform??process.platform,Q=x.exists??NU,J=x.homeDir??zY();if(Z!=="win32"){let z=[FU(Z,J,".local","npm-global","bin","claude"),FU(Z,J,".local","bin","claude")];for(let Y of z)if(Q(Y))return Y}let X=RG0(x);if(X)return X;return null}function Yw(){xw()}function MG0(x={}){let Z=x.platform??process.platform,Q=x.configuredBin===void 0?_x.claude.bin:x.configuredBin;if(Q){if(!(x.exists??NU)(Q))throw Error(`lodestar: [claude].bin not found: ${Q} (config.toml)`);if(Z==="win32"&&sP(Q))return{pathToClaudeCodeExecutable:Q,spawnClaudeCodeProcess:oP,description:`windows-shell-shim:${Q}`};return{pathToClaudeCodeExecutable:Q,description:`config:${Q}`}}let J=xw(x);if(!J)return{description:"sdk-default"};if(Z==="win32"&&sP(J))return{pathToClaudeCodeExecutable:J,spawnClaudeCodeProcess:oP,description:`windows-shell-shim:${J}`};return{description:"sdk-default"}}function RG0(x={}){let Z=x.platform??process.platform,Q=x.pathEnv??process.env.PATH??"";if(!Q)return null;let J=x.exists??NU,X=Z==="win32"?["claude.exe","claude.cmd","claude.bat","claude"]:["claude"];for(let z of Q.split(vG0(Z))){if(!z)continue;for(let Y of X){let G=FU(Z,z,Y);if(J(G))return G}}return null}function SG0(){if(process.platform==="win32")return process.env.PATH??"";let x=[M3(zY(),".local","npm-global","bin"),M3(zY(),".local","bin"),M3(zY(),".bun","bin"),...(process.env.PATH??"").split(pP),"/usr/local/bin","/usr/bin","/bin"];return[...new Set(x.filter(Boolean))].join(pP)}function CG0(x){let Z=E7(x);if(!Z)return null;let Q=(Z.input_tokens??0)+(Z.output_tokens??0)+(Z.cache_creation_input_tokens??0)+(Z.cache_read_input_tokens??0);if((Z.total_tokens??Q)<=0)return null;if(Z.total_tokens==null)Z.total_tokens=Q;return Z}function jG0(x){if(!x)return null;let Z=(x.input_tokens??0)+(x.cache_read_input_tokens??0)+(x.cache_creation_input_tokens??0);return Z>0?Z:null}function LU(x){let Z=x.replace(/\//g,"-"),Q=process.env.CLAUDE_CONFIG_DIR||M3(zY(),".claude");return M3(Q,"projects",Z)}function TG0(x,Z){return M3(LU(x),`${Z}.jsonl`)}function IG0(x){let Z;try{Z=eP(x,"utf8")}catch{return null}let Q=Z.split(`
222
222
  `);for(let J=Q.length-1;J>=0;J--){let X=Q[J].trim();if(!X)continue;try{let z=JSON.parse(X);if(z?.type==="assistant"&&z?.message?.usage)return z.message.usage}catch{}}return null}function rP(x){return x&&x.trim()?x:"claude:default"}function cG0(x){if(!x||typeof x!=="object")return{usage:null,contextWindow:null};let Z={},Q=null;for(let X of Object.values(x)){if(!X||typeof X!=="object")continue;let z=X;Z.input_tokens=(Z.input_tokens??0)+L5(z.inputTokens??z.input_tokens),Z.output_tokens=(Z.output_tokens??0)+L5(z.outputTokens??z.output_tokens),Z.reasoning_output_tokens=(Z.reasoning_output_tokens??0)+L5(z.reasoningOutputTokens??z.reasoning_output_tokens),Z.cache_read_input_tokens=(Z.cache_read_input_tokens??0)+L5(z.cacheReadInputTokens??z.cache_read_input_tokens),Z.cache_creation_input_tokens=(Z.cache_creation_input_tokens??0)+L5(z.cacheCreationInputTokens??z.cache_creation_input_tokens);let Y=L5(z.contextWindow??z.context_window);if(Y>0)Q=Math.max(Q??0,Y)}let J=(Z.input_tokens??0)+(Z.output_tokens??0)+(Z.cache_creation_input_tokens??0)+(Z.cache_read_input_tokens??0);if(J<=0)return{usage:null,contextWindow:Q};return Z.total_tokens=J,{usage:Z,contextWindow:Q}}function kX(x){return{...x}}function $U(x){if(!x||typeof x!=="object")return[];return Object.keys(x).slice(0,20)}function qG0(x,Z){let Q=x?{...x}:{},J=(X)=>{let z=Z[X];if(typeof z!=="number"||!Number.isFinite(z))return;Q[X]=(Q[X]??0)+z};return J("total_tokens"),J("input_tokens"),J("output_tokens"),J("reasoning_output_tokens"),J("cache_creation_input_tokens"),J("cache_read_input_tokens"),Q}function L5(x){return typeof x==="number"&&Number.isFinite(x)?x:0}function Zw(x){if(typeof x==="string")return x;if(Array.isArray(x))return x.map((Z)=>{if(typeof Z==="string")return Z;if(Z&&typeof Z==="object"&&typeof Z.text==="string")return Z.text;return JSON.stringify(Z)}).join(`
223
223
  `);return x==null?"":JSON.stringify(x,null,2)}function AG0(x){let Z=Zw(x);try{let Q=JSON.parse(Z);if(Array.isArray(Q)){let J=Q.map((X)=>{if(typeof X==="string")return X;if(X&&typeof X==="object"&&typeof X.text==="string")return X.text;return JSON.stringify(X)}).filter(Boolean);if(J.length>0)return J.join(`
224
224
  `)}}catch{}return Z}function EG0(x){return`server_tool:${x}`}function WY(x){if(typeof x==="string")return x.replace(/https?:\/\/[^\s"'`<>]+/g,"<url-redacted>");if(Array.isArray(x))return x.map((Z)=>WY(Z));if(x&&typeof x==="object"){let Z={};for(let[Q,J]of Object.entries(x))Z[Q]=WY(J);return Z}return x}function bG0(x){let Z=x.match(/Built-in Tool:\s*([A-Za-z0-9_.:-]+)/)?.[1];if(!Z)return null;let Q=x.match(/\*\*Input:\*\*\s*```(?:json)?\s*([\s\S]*?)```/)?.[1]?.trim();if(!Q)return{name:Z,input:{}};try{return{name:Z,input:WY(JSON.parse(Q))}}catch{return{name:Z,input:{raw:WY(Q)}}}}function kG0(x){let Z=x.trim();return Z.includes("Built-in Tool:")||Z.startsWith("**Output:**")&&Z.includes("_result")}function gG0(x){let Z=x.supportedEffortLevels&&x.supportedEffortLevels.length>0?x.supportedEffortLevels:[J3];return{id:v6(x.value),model:v6(x.value),displayName:x.displayName||v6(x.value),description:x.description||"Claude Agent SDK backend",hidden:!1,isDefault:!1,supportedReasoningEfforts:Z.map((Q)=>({reasoningEffort:Q,description:""})),defaultReasoningEffort:Z.includes(J3)?J3:Z[0]}}function uG0(x){if(!x?.settingSources)return[...tP];let Z=x.settingSources.split(",").map((Q)=>Q.trim()).filter(Boolean);return Z.length?Z:[...tP]}function fG0(x){if(!x?.tools)return{type:"preset",preset:"claude_code"};let Z=x.tools.split(",").map((Q)=>Q.trim()).filter(Boolean);return Z.length?Z:{type:"preset",preset:"claude_code"}}function yG0(x){let Z=M3(x,".mcp.json"),Q;try{Q=eP(Z,"utf8")}catch(J){g(`claude-agent-process: project .mcp.json not readable at ${Z}: ${J}`);return}try{let J=JSON.parse(Q);if(J&&typeof J==="object"&&J.mcpServers&&typeof J.mcpServers==="object")return J.mcpServers;g(`claude-agent-process: project .mcp.json has no mcpServers object at ${Z}`);return}catch(J){g(`claude-agent-process: project .mcp.json parse failed at ${Z}: ${J}`);return}}function hG0(x){if(!Qw.includes(x.dialogKind))return null;let Z=x.payload&&typeof x.payload==="object"?x.payload:{},Q=mG0(Z);if(Q.length===0)return null;return{...Z,questions:Q}}function mG0(x){let Z=x.questions;return(Array.isArray(Z)?Z:Z&&typeof Z==="object"?[Z]:[x]).map((J)=>_G0(J)).filter((J)=>J!==null)}function _G0(x){let Z=x&&typeof x==="object"?x:{question:x},Q=UU(Z.question,Z.prompt,Z.title,Z.message,Z.text,Z.label);if(!Q)return null;if(!Q.trim())return null;let J=nG0(Z.options??Z.choices??Z.suggestions);return{...Z,question:Q,options:J,...typeof Z.header==="string"?{header:Z.header}:{},...typeof Z.multiSelect==="boolean"?{multiSelect:Z.multiSelect}:{}}}function nG0(x){if(!Array.isArray(x))return[];return x.map((Z)=>{if(typeof Z==="string")return{label:Z};if(!Z||typeof Z!=="object")return null;let Q=Z,J=UU(Q.label,Q.value,Q.text,Q.title);if(!J?.trim())return null;let X=UU(Q.description,Q.detail,Q.preview);return X?{label:J,description:X}:{label:J}}).filter((Z)=>Z!==null)}function UU(...x){for(let Z of x)if(typeof Z==="string")return Z;return}var aP,XY,Qw,PG0="bypassPermissions",wG0=!0,tP,DU;var OU=E0(()=>{lP();Z3();$x();d9();iP();aP=class aP{items=[];waiters=[];closed=!1;push(x){if(this.closed)throw Error("input stream is closed");let Z=this.waiters.shift();if(Z)Z({value:x,done:!1});else this.items.push(x)}close(){if(this.closed)return;this.closed=!0;while(this.waiters.length)this.waiters.shift()?.({value:void 0,done:!0})}[Symbol.asyncIterator](){return this}next(){if(this.items.length>0)return Promise.resolve({value:this.items.shift(),done:!1});if(this.closed)return Promise.resolve({value:void 0,done:!0});return new Promise((x)=>this.waiters.push(x))}};XY=new Map;Qw=["ask_user_question","askUserQuestion","AskUserQuestion"],tP=["user","project","local"];DU=class DU extends BG0{provider="claude";opts;input=new aP;query=null;alive=!0;expectedExit=!1;started=!1;pendingPermissions=new Map;pendingInjectedContext=[];requestCounter=0;cumulativeUsageFromResults=null;turnActive=!1;emittedToolUseIds=new Set;emittedToolResultIds=new Set;pendingServerToolInputs=[];sessionId=null;lastAssistantUuid=null;lastModel=null;lastEffort=null;lastUsage=null;lastTotalUsage=null;lastResult={cost_usd:null,cost_delta_usd:null,duration_ms:null,num_turns:null,usage:null,subtype:null,is_error:!1};lastContextWindow=null;lastContextTokens=null;constructor(x){super();this.on("error",()=>{}),this.opts=x,this.lastEffort=x.effort,this.lastModel=x.model?v6(x.model):null}sendInitialize(){if(this.started)return;this.started=!0;let x=GU(this.opts.model),Z=this.opts.profile;if(Z)g(`claude-agent-process: project profile active — settingSources=${Z.settingSources??"-"} strictMcp=${Z.strictMcp??!1} tools=${Z.tools??"-"} loadProjectMcp=${Z.loadProjectMcp??!0}`);let Q=uG0(Z),J=fG0(Z),X=Z?.strictMcp===!0,z=Z?.loadProjectMcp!==!1?yG0(this.opts.workDir):void 0;try{let Y=MG0();g(`claude-agent-process: spawn SDK query model=${x??"default"} effort=${this.opts.effort} cwd=${this.opts.workDir} executable=${Y.description}`),this.query=_P({prompt:this.input,options:{cwd:this.opts.workDir,...x?{model:x}:{},effort:this.opts.effort,resume:this.opts.resumeSessionId,...this.opts.resumeSessionAt?{resumeSessionAt:this.opts.resumeSessionAt}:{},...this.opts.forkSession?{forkSession:!0}:{},...Y.pathToClaudeCodeExecutable?{pathToClaudeCodeExecutable:Y.pathToClaudeCodeExecutable}:{},...Y.spawnClaudeCodeProcess?{spawnClaudeCodeProcess:Y.spawnClaudeCodeProcess}:{},permissionMode:PG0,allowDangerouslySkipPermissions:wG0,env:{...process.env,PATH:SG0(),..._x.claude.env},settingSources:Q,tools:J,...X?{strictMcpConfig:!0}:{},...z?{mcpServers:z}:{},toolConfig:{askUserQuestion:{previewFormat:"markdown"}},supportedDialogKinds:[...Qw],onUserDialog:(G,K)=>this.onUserDialog(G,K),includePartialMessages:!1,systemPrompt:{type:"preset",preset:"claude_code",...this.opts.appendSystemPrompt?{append:this.opts.appendSystemPrompt}:{}},stderr:(G)=>{let K=G.trim();if(K)g(`claude-agent-process[stderr]: ${K}`)}}})}catch(Y){this.alive=!1;let G=Y instanceof Error?Y:Error(String(Y));this.emit("error",G),this.emit("exit",{code:1,signal:null,expected:this.expectedExit});return}this.readLoop(this.query)}sendUserText(x,Z=[]){if(!this.alive){g("claude-agent-process: sendUserText ignored on dead process");return}if(!this.started)this.sendInitialize();let Q=Z.length?Z.map((X)=>`[file: ${X}]`).join(" ")+`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leviyuan/lodestar",
3
- "version": "0.12.1",
3
+ "version": "0.12.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -61,6 +61,16 @@
61
61
  "@modelcontextprotocol/sdk": "^1.29.0",
62
62
  "zod": "^4.4.3"
63
63
  },
64
+ "optionalDependencies": {
65
+ "@anthropic-ai/claude-agent-sdk-darwin-arm64": "^0.3.181",
66
+ "@anthropic-ai/claude-agent-sdk-darwin-x64": "^0.3.181",
67
+ "@anthropic-ai/claude-agent-sdk-linux-arm64": "^0.3.181",
68
+ "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "^0.3.181",
69
+ "@anthropic-ai/claude-agent-sdk-linux-x64": "^0.3.181",
70
+ "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "^0.3.181",
71
+ "@anthropic-ai/claude-agent-sdk-win32-arm64": "^0.3.181",
72
+ "@anthropic-ai/claude-agent-sdk-win32-x64": "^0.3.181"
73
+ },
64
74
  "devDependencies": {
65
75
  "@types/bun": "latest",
66
76
  "typescript": "^5.5.0"
@@ -12,6 +12,32 @@
12
12
  // 所以这里只打个提示就 process.exit(0), 不 spawn 任何子进程, 永不卡死。
13
13
 
14
14
  const fs = require('fs')
15
+ const path = require('path')
16
+ const { execFileSync } = require('child_process')
17
+
18
+ // 自愈:确保当前平台的 SDK native binary 已装。走 SDK 默认入口后该 binary 是必需,
19
+ // 但 npm i -g 对 nested platform optional 在某些 npm 版本/历史残留下会漏装。
20
+ // 装漏了就在这里补,不依赖 npm 行为。非交互、stdio ignore,不碰 tty(区别于曾导致
21
+ // macOS 卡死的 readline 向导)。
22
+ ;(function ensureNativeBinary () {
23
+ const base = `claude-agent-sdk-${process.platform}-${process.arch}`
24
+ const variants = process.platform === 'linux' ? [base, `${base}-musl`] : [base]
25
+ const nm = path.join(__dirname, '..', 'node_modules', '@anthropic-ai')
26
+ const has = (name) =>
27
+ fs.existsSync(path.join(nm, name)) ||
28
+ fs.existsSync(path.join(nm, 'claude-agent-sdk', 'node_modules', '@anthropic-ai', name))
29
+ if (variants.some(has)) return
30
+ try {
31
+ const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm'
32
+ execFileSync(npm, ['install', '--include=optional', '--no-save', '--no-audit', '--no-fund'], {
33
+ cwd: path.join(__dirname, '..'),
34
+ stdio: 'ignore',
35
+ timeout: 180000,
36
+ })
37
+ } catch {
38
+ // 补装失败:静默(optional)。daemon 启动时 SDK 会报明确的 "Native CLI binary not found"
39
+ }
40
+ })()
15
41
 
16
42
  function termWrite (msg) {
17
43
  try {