diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 6359208..74c95d2 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "drywall", - "version": "0.3.1", + "version": "0.4.0", "description": "Detect and eliminate code duplication using jscpd", "mcpServers": { "jscpd": { diff --git a/package-lock.json b/package-lock.json index c62cb1a..b968650 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "drywall", - "version": "0.3.1", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "drywall", - "version": "0.3.1", + "version": "0.4.0", "dependencies": { "@modelcontextprotocol/sdk": "^1.12.1", "zod": "^4.0.0" diff --git a/package.json b/package.json index 765135a..3e62fef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "drywall", - "version": "0.3.1", + "version": "0.4.0", "private": true, "type": "module", "scripts": { diff --git a/servers/jscpd.js b/servers/jscpd.js index e179561..fafd38a 100755 --- a/servers/jscpd.js +++ b/servers/jscpd.js @@ -51,7 +51,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs. `:`[${o[c]}\r ]`;continue}r+=o[c],o[c]==="\\"?i=!0:a&&o[c]==="]"?a=!1:!a&&o[c]==="["&&(a=!0)}try{new RegExp(r)}catch{return console.warn(`Could not convert regex pattern at ${t.currentPath.join("/")} to a flag-independent form! Falling back to the flag-ignorant source`),e.source}return r}function Wu(e,t){if(t.target==="openAi"&&console.warn("Warning: OpenAI may not support records in schemas! Try an array of key-value pairs instead."),t.target==="openApi3"&&e.keyType?._def.typeName===k.ZodEnum)return{type:"object",required:e.keyType._def.values,properties:e.keyType._def.values.reduce((o,r)=>({...o,[r]:L(e.valueType._def,{...t,currentPath:[...t.currentPath,"properties",r]})??_e(t)}),{}),additionalProperties:t.rejectedAdditionalProperties};let n={type:"object",additionalProperties:L(e.valueType._def,{...t,currentPath:[...t.currentPath,"additionalProperties"]})??t.allowedAdditionalProperties};if(t.target==="openApi3")return n;if(e.keyType?._def.typeName===k.ZodString&&e.keyType._def.checks?.length){let{type:o,...r}=Gu(e.keyType._def,t);return{...n,propertyNames:r}}else{if(e.keyType?._def.typeName===k.ZodEnum)return{...n,propertyNames:{enum:e.keyType._def.values}};if(e.keyType?._def.typeName===k.ZodBranded&&e.keyType._def.type._def.typeName===k.ZodString&&e.keyType._def.type._def.checks?.length){let{type:o,...r}=Bu(e.keyType._def,t);return{...n,propertyNames:r}}}return n}function a$(e,t){if(t.mapStrategy==="record")return Wu(e,t);let n=L(e.keyType._def,{...t,currentPath:[...t.currentPath,"items","items","0"]})||_e(t),o=L(e.valueType._def,{...t,currentPath:[...t.currentPath,"items","items","1"]})||_e(t);return{type:"array",maxItems:125,items:{type:"array",items:[n,o],minItems:2,maxItems:2}}}function s$(e){let t=e.values,o=Object.keys(e.values).filter(i=>typeof t[t[i]]!="number").map(i=>t[i]),r=Array.from(new Set(o.map(i=>typeof i)));return{type:r.length===1?r[0]==="string"?"string":"number":["string","number"],enum:o}}function c$(e){return e.target==="openAi"?void 0:{not:_e({...e,currentPath:[...e.currentPath,"not"]})}}function u$(e){return e.target==="openApi3"?{enum:["null"],nullable:!0}:{type:"null"}}var qi={ZodString:"string",ZodNumber:"number",ZodBigInt:"integer",ZodBoolean:"boolean",ZodNull:"null"};function d$(e,t){if(t.target==="openApi3")return l$(e,t);let n=e.options instanceof Map?Array.from(e.options.values()):e.options;if(n.every(o=>o._def.typeName in qi&&(!o._def.checks||!o._def.checks.length))){let o=n.reduce((r,i)=>{let a=qi[i._def.typeName];return a&&!r.includes(a)?[...r,a]:r},[]);return{type:o.length>1?o:o[0]}}else if(n.every(o=>o._def.typeName==="ZodLiteral"&&!o.description)){let o=n.reduce((r,i)=>{let a=typeof i._def.value;switch(a){case"string":case"number":case"boolean":return[...r,a];case"bigint":return[...r,"integer"];case"object":if(i._def.value===null)return[...r,"null"];default:return r}},[]);if(o.length===n.length){let r=o.filter((i,a,s)=>s.indexOf(i)===a);return{type:r.length>1?r:r[0],enum:n.reduce((i,a)=>i.includes(a._def.value)?i:[...i,a._def.value],[])}}}else if(n.every(o=>o._def.typeName==="ZodEnum"))return{type:"string",enum:n.reduce((o,r)=>[...o,...r._def.values.filter(i=>!o.includes(i))],[])};return l$(e,t)}var l$=(e,t)=>{let n=(e.options instanceof Map?Array.from(e.options.values()):e.options).map((o,r)=>L(o._def,{...t,currentPath:[...t.currentPath,"anyOf",`${r}`]})).filter(o=>!!o&&(!t.strictUnions||typeof o=="object"&&Object.keys(o).length>0));return n.length?{anyOf:n}:void 0};function p$(e,t){if(["ZodString","ZodNumber","ZodBigInt","ZodBoolean","ZodNull"].includes(e.innerType._def.typeName)&&(!e.innerType._def.checks||!e.innerType._def.checks.length))return t.target==="openApi3"?{type:qi[e.innerType._def.typeName],nullable:!0}:{type:[qi[e.innerType._def.typeName],"null"]};if(t.target==="openApi3"){let o=L(e.innerType._def,{...t,currentPath:[...t.currentPath]});return o&&"$ref"in o?{allOf:[o],nullable:!0}:o&&{...o,nullable:!0}}let n=L(e.innerType._def,{...t,currentPath:[...t.currentPath,"anyOf","0"]});return n&&{anyOf:[n,{type:"null"}]}}function f$(e,t){let n={type:"number"};if(!e.checks)return n;for(let o of e.checks)switch(o.kind){case"int":n.type="integer",dm(n,"type",o.message,t);break;case"min":t.target==="jsonSchema7"?o.inclusive?te(n,"minimum",o.value,o.message,t):te(n,"exclusiveMinimum",o.value,o.message,t):(o.inclusive||(n.exclusiveMinimum=!0),te(n,"minimum",o.value,o.message,t));break;case"max":t.target==="jsonSchema7"?o.inclusive?te(n,"maximum",o.value,o.message,t):te(n,"exclusiveMaximum",o.value,o.message,t):(o.inclusive||(n.exclusiveMaximum=!0),te(n,"maximum",o.value,o.message,t));break;case"multipleOf":te(n,"multipleOf",o.value,o.message,t);break}return n}function m$(e,t){let n=t.target==="openAi",o={type:"object",properties:{}},r=[],i=e.shape();for(let s in i){let c=i[s];if(c===void 0||c._def===void 0)continue;let u=PI(c);u&&n&&(c._def.typeName==="ZodOptional"&&(c=c._def.innerType),c.isNullable()||(c=c.nullable()),u=!1);let l=L(c._def,{...t,currentPath:[...t.currentPath,"properties",s],propertyPath:[...t.currentPath,"properties",s]});l!==void 0&&(o.properties[s]=l,u||r.push(s))}r.length&&(o.required=r);let a=II(e,t);return a!==void 0&&(o.additionalProperties=a),o}function II(e,t){if(e.catchall._def.typeName!=="ZodNever")return L(e.catchall._def,{...t,currentPath:[...t.currentPath,"additionalProperties"]});switch(e.unknownKeys){case"passthrough":return t.allowedAdditionalProperties;case"strict":return t.rejectedAdditionalProperties;case"strip":return t.removeAdditionalStrategy==="strict"?t.allowedAdditionalProperties:t.rejectedAdditionalProperties}}function PI(e){try{return e.isOptional()}catch{return!0}}var h$=(e,t)=>{if(t.currentPath.toString()===t.propertyPath?.toString())return L(e.innerType._def,t);let n=L(e.innerType._def,{...t,currentPath:[...t.currentPath,"anyOf","1"]});return n?{anyOf:[{not:_e(t)},n]}:_e(t)};var g$=(e,t)=>{if(t.pipeStrategy==="input")return L(e.in._def,t);if(t.pipeStrategy==="output")return L(e.out._def,t);let n=L(e.in._def,{...t,currentPath:[...t.currentPath,"allOf","0"]}),o=L(e.out._def,{...t,currentPath:[...t.currentPath,"allOf",n?"1":"0"]});return{allOf:[n,o].filter(r=>r!==void 0)}};function v$(e,t){return L(e.type._def,t)}function y$(e,t){let o={type:"array",uniqueItems:!0,items:L(e.valueType._def,{...t,currentPath:[...t.currentPath,"items"]})};return e.minSize&&te(o,"minItems",e.minSize.value,e.minSize.message,t),e.maxSize&&te(o,"maxItems",e.maxSize.value,e.maxSize.message,t),o}function _$(e,t){return e.rest?{type:"array",minItems:e.items.length,items:e.items.map((n,o)=>L(n._def,{...t,currentPath:[...t.currentPath,"items",`${o}`]})).reduce((n,o)=>o===void 0?n:[...n,o],[]),additionalItems:L(e.rest._def,{...t,currentPath:[...t.currentPath,"additionalItems"]})}:{type:"array",minItems:e.items.length,maxItems:e.items.length,items:e.items.map((n,o)=>L(n._def,{...t,currentPath:[...t.currentPath,"items",`${o}`]})).reduce((n,o)=>o===void 0?n:[...n,o],[])}}function $$(e){return{not:_e(e)}}function b$(e){return _e(e)}var x$=(e,t)=>L(e.innerType._def,t);var k$=(e,t,n)=>{switch(t){case k.ZodString:return Gu(e,n);case k.ZodNumber:return f$(e,n);case k.ZodObject:return m$(e,n);case k.ZodBigInt:return X_(e,n);case k.ZodBoolean:return Y_();case k.ZodDate:return pm(e,n);case k.ZodUndefined:return $$(n);case k.ZodNull:return u$(n);case k.ZodArray:return W_(e,n);case k.ZodUnion:case k.ZodDiscriminatedUnion:return d$(e,n);case k.ZodIntersection:return n$(e,n);case k.ZodTuple:return _$(e,n);case k.ZodRecord:return Wu(e,n);case k.ZodLiteral:return o$(e,n);case k.ZodEnum:return r$(e);case k.ZodNativeEnum:return s$(e);case k.ZodNullable:return p$(e,n);case k.ZodOptional:return h$(e,n);case k.ZodMap:return a$(e,n);case k.ZodSet:return y$(e,n);case k.ZodLazy:return()=>e.getter()._def;case k.ZodPromise:return v$(e,n);case k.ZodNaN:case k.ZodNever:return c$(n);case k.ZodEffects:return t$(e,n);case k.ZodAny:return _e(n);case k.ZodUnknown:return b$(n);case k.ZodDefault:return e$(e,n);case k.ZodBranded:return Bu(e,n);case k.ZodReadonly:return x$(e,n);case k.ZodCatch:return Q_(e,n);case k.ZodPipeline:return g$(e,n);case k.ZodFunction:case k.ZodVoid:case k.ZodSymbol:return;default:return(o=>{})(t)}};function L(e,t,n=!1){let o=t.seen.get(e);if(t.override){let s=t.override?.(e,t,o,n);if(s!==K_)return s}if(o&&!n){let s=TI(o,t);if(s!==void 0)return s}let r={def:e,path:t.currentPath,jsonSchema:void 0};t.seen.set(e,r);let i=k$(e,e.typeName,t),a=typeof i=="function"?L(i(),t):i;if(a&&jI(e,t,a),t.postProcess){let s=t.postProcess(a,e,t);return r.jsonSchema=a,s}return r.jsonSchema=a,a}var TI=(e,t)=>{switch(t.$refStrategy){case"root":return{$ref:e.path.join("/")};case"relative":return{$ref:Ku(t.currentPath,e.path)};case"none":case"seen":return e.path.lengtht.currentPath[o]===n)?(console.warn(`Recursive reference detected at ${t.currentPath.join("/")}! Defaulting to any`),_e(t)):t.$refStrategy==="seen"?_e(t):void 0}},jI=(e,t,n)=>(e.description&&(n.description=e.description,t.markdownDescription&&(n.markdownDescription=e.description)),n);var hm=(e,t)=>{let n=G_(t),o=typeof t=="object"&&t.definitions?Object.entries(t.definitions).reduce((c,[u,l])=>({...c,[u]:L(l._def,{...n,currentPath:[...n.basePath,n.definitionPath,u]},!0)??_e(n)}),{}):void 0,r=typeof t=="string"?t:t?.nameStrategy==="title"?void 0:t?.name,i=L(e._def,r===void 0?n:{...n,currentPath:[...n.basePath,n.definitionPath,r]},!1)??_e(n),a=typeof t=="object"&&t.name!==void 0&&t.nameStrategy==="title"?t.name:void 0;a!==void 0&&(i.title=a),n.flags.hasReferencedOpenAiAnyType&&(o||(o={}),o[n.openAiAnyTypeName]||(o[n.openAiAnyTypeName]={type:["string","number","integer","boolean","array","null"],items:{$ref:n.$refStrategy==="relative"?"1":[...n.basePath,n.definitionPath,n.openAiAnyTypeName].join("/")}}));let s=r===void 0?o?{...i,[n.definitionPath]:o}:i:{$ref:[...n.$refStrategy==="relative"?[]:n.basePath,n.definitionPath,r].join("/"),[n.definitionPath]:{...o,[r]:i}};return n.target==="jsonSchema7"?s.$schema="http://json-schema.org/draft-07/schema#":(n.target==="jsonSchema2019-09"||n.target==="openAi")&&(s.$schema="https://json-schema.org/draft/2019-09/schema#"),n.target==="openAi"&&("anyOf"in s||"oneOf"in s||"allOf"in s||"type"in s&&Array.isArray(s.type))&&console.warn("Warning: OpenAI may not support schemas with unions as roots! Try wrapping it in an object property."),s};function EI(e){return!e||e==="jsonSchema7"||e==="draft-7"?"draft-7":e==="jsonSchema2019-09"||e==="draft-2020-12"?"draft-2020-12":"draft-7"}function gm(e,t){return at(e)?Fr(e,{target:EI(t?.target),io:t?.pipeStrategy??"input"}):hm(e,{strictUnions:t?.strictUnions??!0,pipeStrategy:t?.pipeStrategy??"input"})}function vm(e){let n=fr(e)?.method;if(!n)throw new Error("Schema is missing a method literal");let o=Gc(n);if(typeof o!="string")throw new Error("Schema method literal must be a string");return o}function ym(e,t){let n=pr(e,t);if(!n.success)throw n.error;return n.data}var OI=6e4,Xu=class{constructor(t){this._options=t,this._requestMessageId=0,this._requestHandlers=new Map,this._requestHandlerAbortControllers=new Map,this._notificationHandlers=new Map,this._responseHandlers=new Map,this._progressHandlers=new Map,this._timeoutInfo=new Map,this._pendingDebouncedNotifications=new Set,this._taskProgressTokens=new Map,this._requestResolvers=new Map,this.setNotificationHandler(ju,n=>{this._oncancel(n)}),this.setNotificationHandler(Ou,n=>{this._onprogress(n)}),this.setRequestHandler(Eu,n=>({})),this._taskStore=t?.taskStore,this._taskMessageQueue=t?.taskMessageQueue,this._taskStore&&(this.setRequestHandler(Nu,async(n,o)=>{let r=await this._taskStore.getTask(n.params.taskId,o.sessionId);if(!r)throw new R(C.InvalidParams,"Failed to retrieve task: Task not found");return{...r}}),this.setRequestHandler(Du,async(n,o)=>{let r=async()=>{let i=n.params.taskId;if(this._taskMessageQueue){let s;for(;s=await this._taskMessageQueue.dequeue(i,o.sessionId);){if(s.type==="response"||s.type==="error"){let c=s.message,u=c.id,l=this._requestResolvers.get(u);if(l)if(this._requestResolvers.delete(u),s.type==="response")l(c);else{let d=c,p=new R(d.error.code,d.error.message,d.error.data);l(p)}else{let d=s.type==="response"?"Response":"Error";this._onerror(new Error(`${d} handler missing for request ${u}`))}continue}await this._transport?.send(s.message,{relatedRequestId:o.requestId})}}let a=await this._taskStore.getTask(i,o.sessionId);if(!a)throw new R(C.InvalidParams,`Task not found: ${i}`);if(!gr(a.status))return await this._waitForTaskUpdate(i,o.signal),await r();if(gr(a.status)){let s=await this._taskStore.getTaskResult(i,o.sessionId);return this._clearTaskQueue(i),{...s,_meta:{...s._meta,[hr]:{taskId:i}}}}return await r()};return await r()}),this.setRequestHandler(Zu,async(n,o)=>{try{let{tasks:r,nextCursor:i}=await this._taskStore.listTasks(n.params?.cursor,o.sessionId);return{tasks:r,nextCursor:i,_meta:{}}}catch(r){throw new R(C.InvalidParams,`Failed to list tasks: ${r instanceof Error?r.message:String(r)}`)}}),this.setRequestHandler(Cu,async(n,o)=>{try{let r=await this._taskStore.getTask(n.params.taskId,o.sessionId);if(!r)throw new R(C.InvalidParams,`Task not found: ${n.params.taskId}`);if(gr(r.status))throw new R(C.InvalidParams,`Cannot cancel task in terminal status: ${r.status}`);await this._taskStore.updateTaskStatus(n.params.taskId,"cancelled","Client cancelled task execution.",o.sessionId),this._clearTaskQueue(n.params.taskId);let i=await this._taskStore.getTask(n.params.taskId,o.sessionId);if(!i)throw new R(C.InvalidParams,`Task not found after cancellation: ${n.params.taskId}`);return{_meta:{},...i}}catch(r){throw r instanceof R?r:new R(C.InvalidRequest,`Failed to cancel task: ${r instanceof Error?r.message:String(r)}`)}}))}async _oncancel(t){if(!t.params.requestId)return;this._requestHandlerAbortControllers.get(t.params.requestId)?.abort(t.params.reason)}_setupTimeout(t,n,o,r,i=!1){this._timeoutInfo.set(t,{timeoutId:setTimeout(r,n),startTime:Date.now(),timeout:n,maxTotalTimeout:o,resetTimeoutOnProgress:i,onTimeout:r})}_resetTimeout(t){let n=this._timeoutInfo.get(t);if(!n)return!1;let o=Date.now()-n.startTime;if(n.maxTotalTimeout&&o>=n.maxTotalTimeout)throw this._timeoutInfo.delete(t),R.fromError(C.RequestTimeout,"Maximum total timeout exceeded",{maxTotalTimeout:n.maxTotalTimeout,totalElapsed:o});return clearTimeout(n.timeoutId),n.timeoutId=setTimeout(n.onTimeout,n.timeout),!0}_cleanupTimeout(t){let n=this._timeoutInfo.get(t);n&&(clearTimeout(n.timeoutId),this._timeoutInfo.delete(t))}async connect(t){if(this._transport)throw new Error("Already connected to a transport. Call close() before connecting to a new transport, or use a separate Protocol instance per connection.");this._transport=t;let n=this.transport?.onclose;this._transport.onclose=()=>{n?.(),this._onclose()};let o=this.transport?.onerror;this._transport.onerror=i=>{o?.(i),this._onerror(i)};let r=this._transport?.onmessage;this._transport.onmessage=(i,a)=>{r?.(i,a),Ni(i)||D_(i)?this._onresponse(i):Xf(i)?this._onrequest(i,a):R_(i)?this._onnotification(i):this._onerror(new Error(`Unknown message type: ${JSON.stringify(i)}`))},await this._transport.start()}_onclose(){let t=this._responseHandlers;this._responseHandlers=new Map,this._progressHandlers.clear(),this._taskProgressTokens.clear(),this._pendingDebouncedNotifications.clear();for(let o of this._requestHandlerAbortControllers.values())o.abort();this._requestHandlerAbortControllers.clear();let n=R.fromError(C.ConnectionClosed,"Connection closed");this._transport=void 0,this.onclose?.();for(let o of t.values())o(n)}_onerror(t){this.onerror?.(t)}_onnotification(t){let n=this._notificationHandlers.get(t.method)??this.fallbackNotificationHandler;n!==void 0&&Promise.resolve().then(()=>n(t)).catch(o=>this._onerror(new Error(`Uncaught error in notification handler: ${o}`)))}_onrequest(t,n){let o=this._requestHandlers.get(t.method)??this.fallbackRequestHandler,r=this._transport,i=t.params?._meta?.[hr]?.taskId;if(o===void 0){let l={jsonrpc:"2.0",id:t.id,error:{code:C.MethodNotFound,message:"Method not found"}};i&&this._taskMessageQueue?this._enqueueTaskMessage(i,{type:"error",message:l,timestamp:Date.now()},r?.sessionId).catch(d=>this._onerror(new Error(`Failed to enqueue error response: ${d}`))):r?.send(l).catch(d=>this._onerror(new Error(`Failed to send an error response: ${d}`)));return}let a=new AbortController;this._requestHandlerAbortControllers.set(t.id,a);let s=E_(t.params)?t.params.task:void 0,c=this._taskStore?this.requestTaskStore(t,r?.sessionId):void 0,u={signal:a.signal,sessionId:r?.sessionId,_meta:t.params?._meta,sendNotification:async l=>{if(a.signal.aborted)return;let d={relatedRequestId:t.id};i&&(d.relatedTask={taskId:i}),await this.notification(l,d)},sendRequest:async(l,d,p)=>{if(a.signal.aborted)throw new R(C.ConnectionClosed,"Request was cancelled");let f={...p,relatedRequestId:t.id};i&&!f.relatedTask&&(f.relatedTask={taskId:i});let h=f.relatedTask?.taskId??i;return h&&c&&await c.updateTaskStatus(h,"input_required"),await this.request(l,d,f)},authInfo:n?.authInfo,requestId:t.id,requestInfo:n?.requestInfo,taskId:i,taskStore:c,taskRequestedTtl:s?.ttl,closeSSEStream:n?.closeSSEStream,closeStandaloneSSEStream:n?.closeStandaloneSSEStream};Promise.resolve().then(()=>{s&&this.assertTaskHandlerCapability(t.method)}).then(()=>o(t,u)).then(async l=>{if(a.signal.aborted)return;let d={result:l,jsonrpc:"2.0",id:t.id};i&&this._taskMessageQueue?await this._enqueueTaskMessage(i,{type:"response",message:d,timestamp:Date.now()},r?.sessionId):await r?.send(d)},async l=>{if(a.signal.aborted)return;let d={jsonrpc:"2.0",id:t.id,error:{code:Number.isSafeInteger(l.code)?l.code:C.InternalError,message:l.message??"Internal error",...l.data!==void 0&&{data:l.data}}};i&&this._taskMessageQueue?await this._enqueueTaskMessage(i,{type:"error",message:d,timestamp:Date.now()},r?.sessionId):await r?.send(d)}).catch(l=>this._onerror(new Error(`Failed to send response: ${l}`))).finally(()=>{this._requestHandlerAbortControllers.delete(t.id)})}_onprogress(t){let{progressToken:n,...o}=t.params,r=Number(n),i=this._progressHandlers.get(r);if(!i){this._onerror(new Error(`Received a progress notification for an unknown token: ${JSON.stringify(t)}`));return}let a=this._responseHandlers.get(r),s=this._timeoutInfo.get(r);if(s&&a&&s.resetTimeoutOnProgress)try{this._resetTimeout(r)}catch(c){this._responseHandlers.delete(r),this._progressHandlers.delete(r),this._cleanupTimeout(r),a(c);return}i(o)}_onresponse(t){let n=Number(t.id),o=this._requestResolvers.get(n);if(o){if(this._requestResolvers.delete(n),Ni(t))o(t);else{let a=new R(t.error.code,t.error.message,t.error.data);o(a)}return}let r=this._responseHandlers.get(n);if(r===void 0){this._onerror(new Error(`Received a response for an unknown message ID: ${JSON.stringify(t)}`));return}this._responseHandlers.delete(n),this._cleanupTimeout(n);let i=!1;if(Ni(t)&&t.result&&typeof t.result=="object"){let a=t.result;if(a.task&&typeof a.task=="object"){let s=a.task;typeof s.taskId=="string"&&(i=!0,this._taskProgressTokens.set(s.taskId,n))}}if(i||this._progressHandlers.delete(n),Ni(t))r(t);else{let a=R.fromError(t.error.code,t.error.message,t.error.data);r(a)}}get transport(){return this._transport}async close(){await this._transport?.close()}async*requestStream(t,n,o){let{task:r}=o??{};if(!r){try{yield{type:"result",result:await this.request(t,n,o)}}catch(a){yield{type:"error",error:a instanceof R?a:new R(C.InternalError,String(a))}}return}let i;try{let a=await this.request(t,Gn,o);if(a.task)i=a.task.taskId,yield{type:"taskCreated",task:a.task};else throw new R(C.InternalError,"Task creation did not return a task");for(;;){let s=await this.getTask({taskId:i},o);if(yield{type:"taskStatus",task:s},gr(s.status)){s.status==="completed"?yield{type:"result",result:await this.getTaskResult({taskId:i},n,o)}:s.status==="failed"?yield{type:"error",error:new R(C.InternalError,`Task ${i} failed`)}:s.status==="cancelled"&&(yield{type:"error",error:new R(C.InternalError,`Task ${i} was cancelled`)});return}if(s.status==="input_required"){yield{type:"result",result:await this.getTaskResult({taskId:i},n,o)};return}let c=s.pollInterval??this._options?.defaultTaskPollInterval??1e3;await new Promise(u=>setTimeout(u,c)),o?.signal?.throwIfAborted()}}catch(a){yield{type:"error",error:a instanceof R?a:new R(C.InternalError,String(a))}}}request(t,n,o){let{relatedRequestId:r,resumptionToken:i,onresumptiontoken:a,task:s,relatedTask:c}=o??{};return new Promise((u,l)=>{let d=U=>{l(U)};if(!this._transport){d(new Error("Not connected"));return}if(this._options?.enforceStrictCapabilities===!0)try{this.assertCapabilityForMethod(t.method),s&&this.assertTaskCapability(t.method)}catch(U){d(U);return}o?.signal?.throwIfAborted();let p=this._requestMessageId++,f={...t,jsonrpc:"2.0",id:p};o?.onprogress&&(this._progressHandlers.set(p,o.onprogress),f.params={...t.params,_meta:{...t.params?._meta||{},progressToken:p}}),s&&(f.params={...f.params,task:s}),c&&(f.params={...f.params,_meta:{...f.params?._meta||{},[hr]:c}});let h=U=>{this._responseHandlers.delete(p),this._progressHandlers.delete(p),this._cleanupTimeout(p),this._transport?.send({jsonrpc:"2.0",method:"notifications/cancelled",params:{requestId:p,reason:String(U)}},{relatedRequestId:r,resumptionToken:i,onresumptiontoken:a}).catch(V=>this._onerror(new Error(`Failed to send cancellation: ${V}`)));let D=U instanceof R?U:new R(C.RequestTimeout,String(U));l(D)};this._responseHandlers.set(p,U=>{if(!o?.signal?.aborted){if(U instanceof Error)return l(U);try{let D=pr(n,U.result);D.success?u(D.data):l(D.error)}catch(D){l(D)}}}),o?.signal?.addEventListener("abort",()=>{h(o?.signal?.reason)});let y=o?.timeout??OI,S=()=>h(R.fromError(C.RequestTimeout,"Request timed out",{timeout:y}));this._setupTimeout(p,y,o?.maxTotalTimeout,S,o?.resetTimeoutOnProgress??!1);let P=c?.taskId;if(P){let U=D=>{let V=this._responseHandlers.get(p);V?V(D):this._onerror(new Error(`Response handler missing for side-channeled request ${p}`))};this._requestResolvers.set(p,U),this._enqueueTaskMessage(P,{type:"request",message:f,timestamp:Date.now()}).catch(D=>{this._cleanupTimeout(p),l(D)})}else this._transport.send(f,{relatedRequestId:r,resumptionToken:i,onresumptiontoken:a}).catch(U=>{this._cleanupTimeout(p),l(U)})})}async getTask(t,n){return this.request({method:"tasks/get",params:t},Ru,n)}async getTaskResult(t,n,o){return this.request({method:"tasks/result",params:t},n,o)}async listTasks(t,n){return this.request({method:"tasks/list",params:t},Au,n)}async cancelTask(t,n){return this.request({method:"tasks/cancel",params:t},C_,n)}async notification(t,n){if(!this._transport)throw new Error("Not connected");this.assertNotificationCapability(t.method);let o=n?.relatedTask?.taskId;if(o){let s={...t,jsonrpc:"2.0",params:{...t.params,_meta:{...t.params?._meta||{},[hr]:n.relatedTask}}};await this._enqueueTaskMessage(o,{type:"notification",message:s,timestamp:Date.now()});return}if((this._options?.debouncedNotificationMethods??[]).includes(t.method)&&!t.params&&!n?.relatedRequestId&&!n?.relatedTask){if(this._pendingDebouncedNotifications.has(t.method))return;this._pendingDebouncedNotifications.add(t.method),Promise.resolve().then(()=>{if(this._pendingDebouncedNotifications.delete(t.method),!this._transport)return;let s={...t,jsonrpc:"2.0"};n?.relatedTask&&(s={...s,params:{...s.params,_meta:{...s.params?._meta||{},[hr]:n.relatedTask}}}),this._transport?.send(s,n).catch(c=>this._onerror(c))});return}let a={...t,jsonrpc:"2.0"};n?.relatedTask&&(a={...a,params:{...a.params,_meta:{...a.params?._meta||{},[hr]:n.relatedTask}}}),await this._transport.send(a,n)}setRequestHandler(t,n){let o=vm(t);this.assertRequestHandlerCapability(o),this._requestHandlers.set(o,(r,i)=>{let a=ym(t,r);return Promise.resolve(n(a,i))})}removeRequestHandler(t){this._requestHandlers.delete(t)}assertCanSetRequestHandler(t){if(this._requestHandlers.has(t))throw new Error(`A request handler for ${t} already exists, which would be overridden`)}setNotificationHandler(t,n){let o=vm(t);this._notificationHandlers.set(o,r=>{let i=ym(t,r);return Promise.resolve(n(i))})}removeNotificationHandler(t){this._notificationHandlers.delete(t)}_cleanupTaskProgressHandler(t){let n=this._taskProgressTokens.get(t);n!==void 0&&(this._progressHandlers.delete(n),this._taskProgressTokens.delete(t))}async _enqueueTaskMessage(t,n,o){if(!this._taskStore||!this._taskMessageQueue)throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");let r=this._options?.maxTaskQueueSize;await this._taskMessageQueue.enqueue(t,n,o,r)}async _clearTaskQueue(t,n){if(this._taskMessageQueue){let o=await this._taskMessageQueue.dequeueAll(t,n);for(let r of o)if(r.type==="request"&&Xf(r.message)){let i=r.message.id,a=this._requestResolvers.get(i);a?(a(new R(C.InternalError,"Task cancelled or completed")),this._requestResolvers.delete(i)):this._onerror(new Error(`Resolver missing for request ${i} during task ${t} cleanup`))}}}async _waitForTaskUpdate(t,n){let o=this._options?.defaultTaskPollInterval??1e3;try{let r=await this._taskStore?.getTask(t);r?.pollInterval&&(o=r.pollInterval)}catch{}return new Promise((r,i)=>{if(n.aborted){i(new R(C.InvalidRequest,"Request cancelled"));return}let a=setTimeout(r,o);n.addEventListener("abort",()=>{clearTimeout(a),i(new R(C.InvalidRequest,"Request cancelled"))},{once:!0})})}requestTaskStore(t,n){let o=this._taskStore;if(!o)throw new Error("No task store configured");return{createTask:async r=>{if(!t)throw new Error("No request provided");return await o.createTask(r,t.id,{method:t.method,params:t.params},n)},getTask:async r=>{let i=await o.getTask(r,n);if(!i)throw new R(C.InvalidParams,"Failed to retrieve task: Task not found");return i},storeTaskResult:async(r,i,a)=>{await o.storeTaskResult(r,i,a,n);let s=await o.getTask(r,n);if(s){let c=Ci.parse({method:"notifications/tasks/status",params:s});await this.notification(c),gr(s.status)&&this._cleanupTaskProgressHandler(r)}},getTaskResult:r=>o.getTaskResult(r,n),updateTaskStatus:async(r,i,a)=>{let s=await o.getTask(r,n);if(!s)throw new R(C.InvalidParams,`Task "${r}" not found - it may have been cleaned up`);if(gr(s.status))throw new R(C.InvalidParams,`Cannot update task "${r}" from terminal status "${s.status}" to "${i}". Terminal states (completed, failed, cancelled) cannot transition to other states.`);await o.updateTaskStatus(r,i,a,n);let c=await o.getTask(r,n);if(c){let u=Ci.parse({method:"notifications/tasks/status",params:c});await this.notification(u),gr(c.status)&&this._cleanupTaskProgressHandler(r)}},listTasks:r=>o.listTasks(r,n)}}};function w$(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function S$(e,t){let n={...e};for(let o in t){let r=o,i=t[r];if(i===void 0)continue;let a=n[r];w$(a)&&w$(i)?n[r]={...a,...i}:n[r]=i}return n}var gk=bg(og(),1),vk=bg(hk(),1);function ZN(){let e=new gk.default({strict:!1,validateFormats:!0,validateSchema:!1,allErrors:!0});return(0,vk.default)(e),e}var Ol=class{constructor(t){this._ajv=t??ZN()}getValidator(t){let n="$id"in t&&typeof t.$id=="string"?this._ajv.getSchema(t.$id)??this._ajv.compile(t):this._ajv.compile(t);return o=>n(o)?{valid:!0,data:o,errorMessage:void 0}:{valid:!1,data:void 0,errorMessage:this._ajv.errorsText(n.errors)}}};var Nl=class{constructor(t){this._server=t}requestStream(t,n,o){return this._server.requestStream(t,n,o)}createMessageStream(t,n){let o=this._server.getClientCapabilities();if((t.tools||t.toolChoice)&&!o?.sampling?.tools)throw new Error("Client does not support sampling tools capability.");if(t.messages.length>0){let r=t.messages[t.messages.length-1],i=Array.isArray(r.content)?r.content:[r.content],a=i.some(l=>l.type==="tool_result"),s=t.messages.length>1?t.messages[t.messages.length-2]:void 0,c=s?Array.isArray(s.content)?s.content:[s.content]:[],u=c.some(l=>l.type==="tool_use");if(a){if(i.some(l=>l.type!=="tool_result"))throw new Error("The last message must contain only tool_result content if any is present");if(!u)throw new Error("tool_result blocks are not matching any tool_use from the previous message")}if(u){let l=new Set(c.filter(p=>p.type==="tool_use").map(p=>p.id)),d=new Set(i.filter(p=>p.type==="tool_result").map(p=>p.toolUseId));if(l.size!==d.size||![...l].every(p=>d.has(p)))throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match")}}return this.requestStream({method:"sampling/createMessage",params:t},Li,n)}elicitInputStream(t,n){let o=this._server.getClientCapabilities(),r=t.mode??"form";switch(r){case"url":{if(!o?.elicitation?.url)throw new Error("Client does not support url elicitation.");break}case"form":{if(!o?.elicitation?.form)throw new Error("Client does not support form elicitation.");break}}let i=r==="form"&&t.mode===void 0?{...t,mode:"form"}:t;return this.requestStream({method:"elicitation/create",params:i},Yn,n)}async getTask(t,n){return this._server.getTask({taskId:t},n)}async getTaskResult(t,n,o){return this._server.getTaskResult({taskId:t},n,o)}async listTasks(t,n){return this._server.listTasks(t?{cursor:t}:void 0,n)}async cancelTask(t,n){return this._server.cancelTask({taskId:t},n)}};function yk(e,t,n){if(!e)throw new Error(`${n} does not support task creation (required for ${t})`);switch(t){case"tools/call":if(!e.tools?.call)throw new Error(`${n} does not support task creation for tools/call (required for ${t})`);break;default:break}}function _k(e,t,n){if(!e)throw new Error(`${n} does not support task creation (required for ${t})`);switch(t){case"sampling/createMessage":if(!e.sampling?.createMessage)throw new Error(`${n} does not support task creation for sampling/createMessage (required for ${t})`);break;case"elicitation/create":if(!e.elicitation?.create)throw new Error(`${n} does not support task creation for elicitation/create (required for ${t})`);break;default:break}}var Rl=class extends Xu{constructor(t,n){super(n),this._serverInfo=t,this._loggingLevels=new Map,this.LOG_LEVEL_SEVERITY=new Map(Mi.options.map((o,r)=>[o,r])),this.isMessageIgnored=(o,r)=>{let i=this._loggingLevels.get(r);return i?this.LOG_LEVEL_SEVERITY.get(o)this._oninitialize(o)),this.setNotificationHandler(tm,()=>this.oninitialized?.()),this._capabilities.logging&&this.setRequestHandler(cm,async(o,r)=>{let i=r.sessionId||r.requestInfo?.headers["mcp-session-id"]||void 0,{level:a}=o.params,s=Mi.safeParse(a);return s.success&&this._loggingLevels.set(i,s.data),{}})}get experimental(){return this._experimental||(this._experimental={tasks:new Nl(this)}),this._experimental}registerCapabilities(t){if(this.transport)throw new Error("Cannot register capabilities after connecting to transport");this._capabilities=S$(this._capabilities,t)}setRequestHandler(t,n){let r=fr(t)?.method;if(!r)throw new Error("Schema is missing a method literal");let i;if(at(r)){let s=r;i=s._zod?.def?.value??s.value}else{let s=r;i=s._def?.value??s.value}if(typeof i!="string")throw new Error("Schema method literal must be a string");if(i==="tools/call"){let s=async(c,u)=>{let l=pr(Xn,c);if(!l.success){let h=l.error instanceof Error?l.error.message:String(l.error);throw new R(C.InvalidParams,`Invalid tools/call request: ${h}`)}let{params:d}=l.data,p=await Promise.resolve(n(c,u));if(d.task){let h=pr(Gn,p);if(!h.success){let y=h.error instanceof Error?h.error.message:String(h.error);throw new R(C.InvalidParams,`Invalid task creation result: ${y}`)}return h.data}let f=pr(Ju,p);if(!f.success){let h=f.error instanceof Error?f.error.message:String(f.error);throw new R(C.InvalidParams,`Invalid tools/call result: ${h}`)}return f.data};return super.setRequestHandler(t,s)}return super.setRequestHandler(t,n)}assertCapabilityForMethod(t){switch(t){case"sampling/createMessage":if(!this._clientCapabilities?.sampling)throw new Error(`Client does not support sampling (required for ${t})`);break;case"elicitation/create":if(!this._clientCapabilities?.elicitation)throw new Error(`Client does not support elicitation (required for ${t})`);break;case"roots/list":if(!this._clientCapabilities?.roots)throw new Error(`Client does not support listing roots (required for ${t})`);break;case"ping":break}}assertNotificationCapability(t){switch(t){case"notifications/message":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${t})`);break;case"notifications/resources/updated":case"notifications/resources/list_changed":if(!this._capabilities.resources)throw new Error(`Server does not support notifying about resources (required for ${t})`);break;case"notifications/tools/list_changed":if(!this._capabilities.tools)throw new Error(`Server does not support notifying of tool list changes (required for ${t})`);break;case"notifications/prompts/list_changed":if(!this._capabilities.prompts)throw new Error(`Server does not support notifying of prompt list changes (required for ${t})`);break;case"notifications/elicitation/complete":if(!this._clientCapabilities?.elicitation?.url)throw new Error(`Client does not support URL elicitation (required for ${t})`);break;case"notifications/cancelled":break;case"notifications/progress":break}}assertRequestHandlerCapability(t){if(this._capabilities)switch(t){case"completion/complete":if(!this._capabilities.completions)throw new Error(`Server does not support completions (required for ${t})`);break;case"logging/setLevel":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${t})`);break;case"prompts/get":case"prompts/list":if(!this._capabilities.prompts)throw new Error(`Server does not support prompts (required for ${t})`);break;case"resources/list":case"resources/templates/list":case"resources/read":if(!this._capabilities.resources)throw new Error(`Server does not support resources (required for ${t})`);break;case"tools/call":case"tools/list":if(!this._capabilities.tools)throw new Error(`Server does not support tools (required for ${t})`);break;case"tasks/get":case"tasks/list":case"tasks/result":case"tasks/cancel":if(!this._capabilities.tasks)throw new Error(`Server does not support tasks capability (required for ${t})`);break;case"ping":case"initialize":break}}assertTaskCapability(t){_k(this._clientCapabilities?.tasks?.requests,t,"Client")}assertTaskHandlerCapability(t){this._capabilities&&yk(this._capabilities.tasks?.requests,t,"Server")}async _oninitialize(t){let n=t.params.protocolVersion;return this._clientCapabilities=t.params.capabilities,this._clientVersion=t.params.clientInfo,{protocolVersion:P_.includes(n)?n:Gf,capabilities:this.getCapabilities(),serverInfo:this._serverInfo,...this._instructions&&{instructions:this._instructions}}}getClientCapabilities(){return this._clientCapabilities}getClientVersion(){return this._clientVersion}getCapabilities(){return this._capabilities}async ping(){return this.request({method:"ping"},Tu)}async createMessage(t,n){if((t.tools||t.toolChoice)&&!this._clientCapabilities?.sampling?.tools)throw new Error("Client does not support sampling tools capability.");if(t.messages.length>0){let o=t.messages[t.messages.length-1],r=Array.isArray(o.content)?o.content:[o.content],i=r.some(u=>u.type==="tool_result"),a=t.messages.length>1?t.messages[t.messages.length-2]:void 0,s=a?Array.isArray(a.content)?a.content:[a.content]:[],c=s.some(u=>u.type==="tool_use");if(i){if(r.some(u=>u.type!=="tool_result"))throw new Error("The last message must contain only tool_result content if any is present");if(!c)throw new Error("tool_result blocks are not matching any tool_use from the previous message")}if(c){let u=new Set(s.filter(d=>d.type==="tool_use").map(d=>d.id)),l=new Set(r.filter(d=>d.type==="tool_result").map(d=>d.toolUseId));if(u.size!==l.size||![...u].every(d=>l.has(d)))throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match")}}return t.tools?this.request({method:"sampling/createMessage",params:t},um,n):this.request({method:"sampling/createMessage",params:t},Li,n)}async elicitInput(t,n){switch(t.mode??"form"){case"url":{if(!this._clientCapabilities?.elicitation?.url)throw new Error("Client does not support url elicitation.");let r=t;return this.request({method:"elicitation/create",params:r},Yn,n)}case"form":{if(!this._clientCapabilities?.elicitation?.form)throw new Error("Client does not support form elicitation.");let r=t.mode==="form"?t:{...t,mode:"form"},i=await this.request({method:"elicitation/create",params:r},Yn,n);if(i.action==="accept"&&i.content&&r.requestedSchema)try{let s=this._jsonSchemaValidator.getValidator(r.requestedSchema)(i.content);if(!s.valid)throw new R(C.InvalidParams,`Elicitation response content does not match requested schema: ${s.errorMessage}`)}catch(a){throw a instanceof R?a:new R(C.InternalError,`Error validating elicitation response: ${a instanceof Error?a.message:String(a)}`)}return i}}}createElicitationCompletionNotifier(t,n){if(!this._clientCapabilities?.elicitation?.url)throw new Error("Client does not support URL elicitation (required for notifications/elicitation/complete)");return()=>this.notification({method:"notifications/elicitation/complete",params:{elicitationId:t}},n)}async listRoots(t,n){return this.request({method:"roots/list",params:t},lm,n)}async sendLoggingMessage(t,n){if(this._capabilities.logging&&!this.isMessageIgnored(t.level,n))return this.notification({method:"notifications/message",params:t})}async sendResourceUpdated(t){return this.notification({method:"notifications/resources/updated",params:t})}async sendResourceListChanged(){return this.notification({method:"notifications/resources/list_changed"})}async sendToolListChanged(){return this.notification({method:"notifications/tools/list_changed"})}async sendPromptListChanged(){return this.notification({method:"notifications/prompts/list_changed"})}};var bk=Symbol.for("mcp.completable");function pg(e){return!!e&&typeof e=="object"&&bk in e}function xk(e){return e[bk]?.complete}var $k;(function(e){e.Completable="McpCompletable"})($k||($k={}));var AN=/^[A-Za-z0-9._-]{1,128}$/;function CN(e){let t=[];if(e.length===0)return{isValid:!1,warnings:["Tool name cannot be empty"]};if(e.length>128)return{isValid:!1,warnings:[`Tool name exceeds maximum length of 128 characters (current: ${e.length})`]};if(e.includes(" ")&&t.push("Tool name contains spaces, which may cause parsing issues"),e.includes(",")&&t.push("Tool name contains commas, which may cause parsing issues"),(e.startsWith("-")||e.endsWith("-"))&&t.push("Tool name starts or ends with a dash, which may cause parsing issues in some contexts"),(e.startsWith(".")||e.endsWith("."))&&t.push("Tool name starts or ends with a dot, which may cause parsing issues in some contexts"),!AN.test(e)){let n=e.split("").filter(o=>!/[A-Za-z0-9._-]/.test(o)).filter((o,r,i)=>i.indexOf(o)===r);return t.push(`Tool name contains invalid characters: ${n.map(o=>`"${o}"`).join(", ")}`,"Allowed characters are: A-Z, a-z, 0-9, underscore (_), dash (-), and dot (.)"),{isValid:!1,warnings:t}}return{isValid:!0,warnings:t}}function UN(e,t){if(t.length>0){console.warn(`Tool name validation warning for "${e}":`);for(let n of t)console.warn(` - ${n}`);console.warn("Tool registration will proceed, but this may cause compatibility issues."),console.warn("Consider updating the tool name to conform to the MCP tool naming standard."),console.warn("See SEP: Specify Format for Tool Names (https://github.com/modelcontextprotocol/modelcontextprotocol/issues/986) for more details.")}}function fg(e){let t=CN(e);return UN(e,t.warnings),t.isValid}var Dl=class{constructor(t){this._mcpServer=t}registerToolTask(t,n,o){let r={taskSupport:"required",...n.execution};if(r.taskSupport==="forbidden")throw new Error(`Cannot register task-based tool '${t}' with taskSupport 'forbidden'. Use registerTool() instead.`);return this._mcpServer._createRegisteredTool(t,n.title,n.description,n.inputSchema,n.outputSchema,n.annotations,r,n._meta,o)}};var Zl=class{constructor(t,n){this._registeredResources={},this._registeredResourceTemplates={},this._registeredTools={},this._registeredPrompts={},this._toolHandlersInitialized=!1,this._completionHandlerInitialized=!1,this._resourceHandlersInitialized=!1,this._promptHandlersInitialized=!1,this.server=new Rl(t,n)}get experimental(){return this._experimental||(this._experimental={tasks:new Dl(this)}),this._experimental}async connect(t){return await this.server.connect(t)}async close(){await this.server.close()}setToolRequestHandlers(){this._toolHandlersInitialized||(this.server.assertCanSetRequestHandler(Sr(Fu)),this.server.assertCanSetRequestHandler(Sr(Xn)),this.server.registerCapabilities({tools:{listChanged:!0}}),this.server.setRequestHandler(Fu,()=>({tools:Object.entries(this._registeredTools).filter(([,t])=>t.enabled).map(([t,n])=>{let o={name:t,title:n.title,description:n.description,inputSchema:(()=>{let r=Cn(n.inputSchema);return r?gm(r,{strictUnions:!0,pipeStrategy:"input"}):MN})(),annotations:n.annotations,execution:n.execution,_meta:n._meta};if(n.outputSchema){let r=Cn(n.outputSchema);r&&(o.outputSchema=gm(r,{strictUnions:!0,pipeStrategy:"output"}))}return o})})),this.server.setRequestHandler(Xn,async(t,n)=>{try{let o=this._registeredTools[t.params.name];if(!o)throw new R(C.InvalidParams,`Tool ${t.params.name} not found`);if(!o.enabled)throw new R(C.InvalidParams,`Tool ${t.params.name} disabled`);let r=!!t.params.task,i=o.execution?.taskSupport,a="createTask"in o.handler;if((i==="required"||i==="optional")&&!a)throw new R(C.InternalError,`Tool ${t.params.name} has taskSupport '${i}' but was not registered with registerToolTask`);if(i==="required"&&!r)throw new R(C.MethodNotFound,`Tool ${t.params.name} requires task augmentation (taskSupport: 'required')`);if(i==="optional"&&!r&&a)return await this.handleAutomaticTaskPolling(o,t,n);let s=await this.validateToolInput(o,t.params.arguments,t.params.name),c=await this.executeToolHandler(o,s,n);return r||await this.validateToolOutput(o,c,t.params.name),c}catch(o){if(o instanceof R&&o.code===C.UrlElicitationRequired)throw o;return this.createToolError(o instanceof Error?o.message:String(o))}}),this._toolHandlersInitialized=!0)}createToolError(t){return{content:[{type:"text",text:t}],isError:!0}}async validateToolInput(t,n,o){if(!t.inputSchema)return;let i=Cn(t.inputSchema)??t.inputSchema,a=await Kc(i,n);if(!a.success){let s="error"in a?a.error:"Unknown error",c=Bc(s);throw new R(C.InvalidParams,`Input validation error: Invalid arguments for tool ${o}: ${c}`)}return a.data}async validateToolOutput(t,n,o){if(!t.outputSchema||!("content"in n)||n.isError)return;if(!n.structuredContent)throw new R(C.InvalidParams,`Output validation error: Tool ${o} has an output schema but no structured content was provided`);let r=Cn(t.outputSchema),i=await Kc(r,n.structuredContent);if(!i.success){let a="error"in i?i.error:"Unknown error",s=Bc(a);throw new R(C.InvalidParams,`Output validation error: Invalid structured content for tool ${o}: ${s}`)}}async executeToolHandler(t,n,o){let r=t.handler;if("createTask"in r){if(!o.taskStore)throw new Error("No task store provided.");let a={...o,taskStore:o.taskStore};if(t.inputSchema){let s=r;return await Promise.resolve(s.createTask(n,a))}else{let s=r;return await Promise.resolve(s.createTask(a))}}if(t.inputSchema){let a=r;return await Promise.resolve(a(n,o))}else{let a=r;return await Promise.resolve(a(o))}}async handleAutomaticTaskPolling(t,n,o){if(!o.taskStore)throw new Error("No task store provided for task-capable tool.");let r=await this.validateToolInput(t,n.params.arguments,n.params.name),i=t.handler,a={...o,taskStore:o.taskStore},s=r?await Promise.resolve(i.createTask(r,a)):await Promise.resolve(i.createTask(a)),c=s.task.taskId,u=s.task,l=u.pollInterval??5e3;for(;u.status!=="completed"&&u.status!=="failed"&&u.status!=="cancelled";){await new Promise(p=>setTimeout(p,l));let d=await o.taskStore.getTask(c);if(!d)throw new R(C.InternalError,`Task ${c} not found during polling`);u=d}return await o.taskStore.getTaskResult(c)}setCompletionRequestHandler(){this._completionHandlerInitialized||(this.server.assertCanSetRequestHandler(Sr(Hu)),this.server.registerCapabilities({completions:{}}),this.server.setRequestHandler(Hu,async t=>{switch(t.params.ref.type){case"ref/prompt":return F_(t),this.handlePromptCompletion(t,t.params.ref);case"ref/resource":return J_(t),this.handleResourceCompletion(t,t.params.ref);default:throw new R(C.InvalidParams,`Invalid completion reference: ${t.params.ref}`)}}),this._completionHandlerInitialized=!0)}async handlePromptCompletion(t,n){let o=this._registeredPrompts[n.name];if(!o)throw new R(C.InvalidParams,`Prompt ${n.name} not found`);if(!o.enabled)throw new R(C.InvalidParams,`Prompt ${n.name} disabled`);if(!o.argsSchema)return ya;let i=fr(o.argsSchema)?.[t.params.argument.name];if(!pg(i))return ya;let a=xk(i);if(!a)return ya;let s=await a(t.params.argument.value,t.params.context);return wk(s)}async handleResourceCompletion(t,n){let o=Object.values(this._registeredResourceTemplates).find(a=>a.resourceTemplate.uriTemplate.toString()===n.uri);if(!o){if(this._registeredResources[n.uri])return ya;throw new R(C.InvalidParams,`Resource template ${t.params.ref.uri} not found`)}let r=o.resourceTemplate.completeCallback(t.params.argument.name);if(!r)return ya;let i=await r(t.params.argument.value,t.params.context);return wk(i)}setResourceRequestHandlers(){this._resourceHandlersInitialized||(this.server.assertCanSetRequestHandler(Sr(Uu)),this.server.assertCanSetRequestHandler(Sr(Mu)),this.server.assertCanSetRequestHandler(Sr(Lu)),this.server.registerCapabilities({resources:{listChanged:!0}}),this.server.setRequestHandler(Uu,async(t,n)=>{let o=Object.entries(this._registeredResources).filter(([i,a])=>a.enabled).map(([i,a])=>({uri:i,name:a.name,...a.metadata})),r=[];for(let i of Object.values(this._registeredResourceTemplates)){if(!i.resourceTemplate.listCallback)continue;let a=await i.resourceTemplate.listCallback(n);for(let s of a.resources)r.push({...i.metadata,...s})}return{resources:[...o,...r]}}),this.server.setRequestHandler(Mu,async()=>({resourceTemplates:Object.entries(this._registeredResourceTemplates).map(([n,o])=>({name:n,uriTemplate:o.resourceTemplate.uriTemplate.toString(),...o.metadata}))})),this.server.setRequestHandler(Lu,async(t,n)=>{let o=new URL(t.params.uri),r=this._registeredResources[o.toString()];if(r){if(!r.enabled)throw new R(C.InvalidParams,`Resource ${o} disabled`);return r.readCallback(o,n)}for(let i of Object.values(this._registeredResourceTemplates)){let a=i.resourceTemplate.uriTemplate.match(o.toString());if(a)return i.readCallback(o,a,n)}throw new R(C.InvalidParams,`Resource ${o} not found`)}),this._resourceHandlersInitialized=!0)}setPromptRequestHandlers(){this._promptHandlersInitialized||(this.server.assertCanSetRequestHandler(Sr(qu)),this.server.assertCanSetRequestHandler(Sr(Vu)),this.server.registerCapabilities({prompts:{listChanged:!0}}),this.server.setRequestHandler(qu,()=>({prompts:Object.entries(this._registeredPrompts).filter(([,t])=>t.enabled).map(([t,n])=>({name:t,title:n.title,description:n.description,arguments:n.argsSchema?qN(n.argsSchema):void 0}))})),this.server.setRequestHandler(Vu,async(t,n)=>{let o=this._registeredPrompts[t.params.name];if(!o)throw new R(C.InvalidParams,`Prompt ${t.params.name} not found`);if(!o.enabled)throw new R(C.InvalidParams,`Prompt ${t.params.name} disabled`);if(o.argsSchema){let r=Cn(o.argsSchema),i=await Kc(r,t.params.arguments);if(!i.success){let c="error"in i?i.error:"Unknown error",u=Bc(c);throw new R(C.InvalidParams,`Invalid arguments for prompt ${t.params.name}: ${u}`)}let a=i.data,s=o.callback;return await Promise.resolve(s(a,n))}else{let r=o.callback;return await Promise.resolve(r(n))}}),this._promptHandlersInitialized=!0)}resource(t,n,...o){let r;typeof o[0]=="object"&&(r=o.shift());let i=o[0];if(typeof n=="string"){if(this._registeredResources[n])throw new Error(`Resource ${n} is already registered`);let a=this._createRegisteredResource(t,void 0,n,r,i);return this.setResourceRequestHandlers(),this.sendResourceListChanged(),a}else{if(this._registeredResourceTemplates[t])throw new Error(`Resource template ${t} is already registered`);let a=this._createRegisteredResourceTemplate(t,void 0,n,r,i);return this.setResourceRequestHandlers(),this.sendResourceListChanged(),a}}registerResource(t,n,o,r){if(typeof n=="string"){if(this._registeredResources[n])throw new Error(`Resource ${n} is already registered`);let i=this._createRegisteredResource(t,o.title,n,o,r);return this.setResourceRequestHandlers(),this.sendResourceListChanged(),i}else{if(this._registeredResourceTemplates[t])throw new Error(`Resource template ${t} is already registered`);let i=this._createRegisteredResourceTemplate(t,o.title,n,o,r);return this.setResourceRequestHandlers(),this.sendResourceListChanged(),i}}_createRegisteredResource(t,n,o,r,i){let a={name:t,title:n,metadata:r,readCallback:i,enabled:!0,disable:()=>a.update({enabled:!1}),enable:()=>a.update({enabled:!0}),remove:()=>a.update({uri:null}),update:s=>{typeof s.uri<"u"&&s.uri!==o&&(delete this._registeredResources[o],s.uri&&(this._registeredResources[s.uri]=a)),typeof s.name<"u"&&(a.name=s.name),typeof s.title<"u"&&(a.title=s.title),typeof s.metadata<"u"&&(a.metadata=s.metadata),typeof s.callback<"u"&&(a.readCallback=s.callback),typeof s.enabled<"u"&&(a.enabled=s.enabled),this.sendResourceListChanged()}};return this._registeredResources[o]=a,a}_createRegisteredResourceTemplate(t,n,o,r,i){let a={resourceTemplate:o,title:n,metadata:r,readCallback:i,enabled:!0,disable:()=>a.update({enabled:!1}),enable:()=>a.update({enabled:!0}),remove:()=>a.update({name:null}),update:u=>{typeof u.name<"u"&&u.name!==t&&(delete this._registeredResourceTemplates[t],u.name&&(this._registeredResourceTemplates[u.name]=a)),typeof u.title<"u"&&(a.title=u.title),typeof u.template<"u"&&(a.resourceTemplate=u.template),typeof u.metadata<"u"&&(a.metadata=u.metadata),typeof u.callback<"u"&&(a.readCallback=u.callback),typeof u.enabled<"u"&&(a.enabled=u.enabled),this.sendResourceListChanged()}};this._registeredResourceTemplates[t]=a;let s=o.uriTemplate.variableNames;return Array.isArray(s)&&s.some(u=>!!o.completeCallback(u))&&this.setCompletionRequestHandler(),a}_createRegisteredPrompt(t,n,o,r,i){let a={title:n,description:o,argsSchema:r===void 0?void 0:Jr(r),callback:i,enabled:!0,disable:()=>a.update({enabled:!1}),enable:()=>a.update({enabled:!0}),remove:()=>a.update({name:null}),update:s=>{typeof s.name<"u"&&s.name!==t&&(delete this._registeredPrompts[t],s.name&&(this._registeredPrompts[s.name]=a)),typeof s.title<"u"&&(a.title=s.title),typeof s.description<"u"&&(a.description=s.description),typeof s.argsSchema<"u"&&(a.argsSchema=Jr(s.argsSchema)),typeof s.callback<"u"&&(a.callback=s.callback),typeof s.enabled<"u"&&(a.enabled=s.enabled),this.sendPromptListChanged()}};return this._registeredPrompts[t]=a,r&&Object.values(r).some(c=>{let u=c instanceof Kn?c._def?.innerType:c;return pg(u)})&&this.setCompletionRequestHandler(),a}_createRegisteredTool(t,n,o,r,i,a,s,c,u){fg(t);let l={title:n,description:o,inputSchema:kk(r),outputSchema:kk(i),annotations:a,execution:s,_meta:c,handler:u,enabled:!0,disable:()=>l.update({enabled:!1}),enable:()=>l.update({enabled:!0}),remove:()=>l.update({name:null}),update:d=>{typeof d.name<"u"&&d.name!==t&&(typeof d.name=="string"&&fg(d.name),delete this._registeredTools[t],d.name&&(this._registeredTools[d.name]=l)),typeof d.title<"u"&&(l.title=d.title),typeof d.description<"u"&&(l.description=d.description),typeof d.paramsSchema<"u"&&(l.inputSchema=Jr(d.paramsSchema)),typeof d.outputSchema<"u"&&(l.outputSchema=Jr(d.outputSchema)),typeof d.callback<"u"&&(l.handler=d.callback),typeof d.annotations<"u"&&(l.annotations=d.annotations),typeof d._meta<"u"&&(l._meta=d._meta),typeof d.enabled<"u"&&(l.enabled=d.enabled),this.sendToolListChanged()}};return this._registeredTools[t]=l,this.setToolRequestHandlers(),this.sendToolListChanged(),l}tool(t,...n){if(this._registeredTools[t])throw new Error(`Tool ${t} is already registered`);let o,r,i,a;if(typeof n[0]=="string"&&(o=n.shift()),n.length>1){let c=n[0];mg(c)?(r=n.shift(),n.length>1&&typeof n[0]=="object"&&n[0]!==null&&!mg(n[0])&&(a=n.shift())):typeof c=="object"&&c!==null&&(a=n.shift())}let s=n[0];return this._createRegisteredTool(t,void 0,o,r,i,a,{taskSupport:"forbidden"},void 0,s)}registerTool(t,n,o){if(this._registeredTools[t])throw new Error(`Tool ${t} is already registered`);let{title:r,description:i,inputSchema:a,outputSchema:s,annotations:c,_meta:u}=n;return this._createRegisteredTool(t,r,i,a,s,c,{taskSupport:"forbidden"},u,o)}prompt(t,...n){if(this._registeredPrompts[t])throw new Error(`Prompt ${t} is already registered`);let o;typeof n[0]=="string"&&(o=n.shift());let r;n.length>1&&(r=n.shift());let i=n[0],a=this._createRegisteredPrompt(t,void 0,o,r,i);return this.setPromptRequestHandlers(),this.sendPromptListChanged(),a}registerPrompt(t,n,o){if(this._registeredPrompts[t])throw new Error(`Prompt ${t} is already registered`);let{title:r,description:i,argsSchema:a}=n,s=this._createRegisteredPrompt(t,r,i,a,o);return this.setPromptRequestHandlers(),this.sendPromptListChanged(),s}isConnected(){return this.server.transport!==void 0}async sendLoggingMessage(t,n){return this.server.sendLoggingMessage(t,n)}sendResourceListChanged(){this.isConnected()&&this.server.sendResourceListChanged()}sendToolListChanged(){this.isConnected()&&this.server.sendToolListChanged()}sendPromptListChanged(){this.isConnected()&&this.server.sendPromptListChanged()}};var MN={type:"object",properties:{}};function Sk(e){return e!==null&&typeof e=="object"&&"parse"in e&&typeof e.parse=="function"&&"safeParse"in e&&typeof e.safeParse=="function"}function LN(e){return"_def"in e||"_zod"in e||Sk(e)}function mg(e){return typeof e!="object"||e===null||LN(e)?!1:Object.keys(e).length===0?!0:Object.values(e).some(Sk)}function kk(e){if(e)return mg(e)?Jr(e):e}function qN(e){let t=fr(e);return t?Object.entries(t).map(([n,o])=>{let r=hy(o),i=gy(o);return{name:n,description:r,required:!i}}):[]}function Sr(e){let n=fr(e)?.method;if(!n)throw new Error("Schema is missing a method literal");let o=Gc(n);if(typeof o=="string")return o;throw new Error("Schema method literal must be a string")}function wk(e){return{completion:{values:e.slice(0,100),total:e.length,hasMore:e.length>100}}}var ya={completion:{values:[],hasMore:!1}};import Ik from"node:process";var Al=class{append(t){this._buffer=this._buffer?Buffer.concat([this._buffer,t]):t}readMessage(){if(!this._buffer)return null;let t=this._buffer.indexOf(` `);if(t===-1)return null;let n=this._buffer.toString("utf8",0,t).replace(/\r$/,"");return this._buffer=this._buffer.subarray(t+1),VN(n)}clear(){this._buffer=void 0}};function VN(e){return Z_.parse(JSON.parse(e))}function zk(e){return JSON.stringify(e)+` -`}var Cl=class{constructor(t=Ik.stdin,n=Ik.stdout){this._stdin=t,this._stdout=n,this._readBuffer=new Al,this._started=!1,this._ondata=o=>{this._readBuffer.append(o),this.processReadBuffer()},this._onerror=o=>{this.onerror?.(o)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(;;)try{let t=this._readBuffer.readMessage();if(t===null)break;this.onmessage?.(t)}catch(t){this.onerror?.(t)}}async close(){this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.listenerCount("data")===0&&this._stdin.pause(),this._readBuffer.clear(),this.onclose?.()}send(t){return new Promise(n=>{let o=zk(t);this._stdout.write(o)?n():this._stdout.once("drain",n)})}};import{execFile as FN}from"node:child_process";import{readFile as jk,mkdtemp as JN,open as HN}from"node:fs/promises";import{join as Ul,dirname as KN}from"node:path";import{tmpdir as BN}from"node:os";import{existsSync as Ml}from"node:fs";var Ek="0.3.1",hg="5.0.12";function gg(e){return Number.parseInt(e,10)}async function Ok(){let e=await JN(Ul(BN(),"drywall-report-"));return{reportDir:e,reportPath:Ul(e,"jscpd-report.json")}}var GN=new Set(["jscpdVersion","respectGitignore","path","maxDuplicates","maxFragmentLength"]);function Pk(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}var WN=new Set(["ignore","ignorePattern","format"]);async function Nk(){try{let e=await jk(".drywallrc.json","utf8");return JSON.parse(e)}catch{return{}}}function Rk(e,t,n){let{jscpdVersion:o,respectGitignore:r,...i}=e,a=gg(o||hg),s={...i,...t},c=[];a>=5?r===!1&&c.push("--no-gitignore"):r!==!1&&c.push("--gitignore");for(let[u,l]of Object.entries(s)){if(GN.has(u))continue;if(u==="reporters")throw new Error('"reporters" is not configurable in DRYwall; it always uses the json reporter that the server reads. Remove it from your config.');let d=`--${Pk(u)}`;if(Array.isArray(l)){if(!WN.has(u))throw new Error(`Config key "${u}" does not accept multiple values; jscpd's --${Pk(u)} takes a single value. Provide a string, not an array.`);c.push(d,l.map(String).join(","))}else typeof l=="boolean"?l&&c.push(d):l!=null&&c.push(d,String(l))}return c.push("--reporters","json","--output",n),c}function Dk(e){return process.platform==="win32"&&typeof e=="string"?e.replace(/\\/g,"/"):e}var XN=/^\d+\.\d+\.\d+(-[\w.]+)?$/;function YN(e){if(process.platform!=="win32")return{command:"npx",spawnArgs:e,options:{}};let t=Ul(KN(process.execPath),"node_modules","npm","bin","npx-cli.js");return Ml(t)?{command:process.execPath,spawnArgs:[t,...e],options:{}}:{command:"npx.cmd",spawnArgs:e,options:{shell:!0}}}function Zk(e,t,n){if(!XN.test(e))throw new Error(`Invalid jscpd version: "${e}"`);let o=[`jscpd@${e}`,...t],r=["npx",...o],{command:i,spawnArgs:a,options:s}=YN(o);return new Promise((c,u)=>{FN(i,a,s,(l,d,p)=>{let f=n&&Ml(n)||p.includes("Clone found");l&&!f?u(new Error(p||l.message)):c({cmd:r,stdout:d,stderr:p})})})}var vg=20,yg=500;function Tk(e,t){if(!t||Ml(e))return e;let n=Ul(t,e);return Ml(n)?n:e}async function QN(e,t,n,o){let r;try{let i=Math.min(n-t,o*4+4);if(i<=0)return"";r=await HN(e,"r");let a=Buffer.alloc(i),{bytesRead:s}=await r.read(a,0,i,t);return a.toString("utf8",0,s)}catch{return""}finally{await r?.close()}}async function e4(e,t,n,o){try{return o.has(e)||o.set(e,(await jk(e,"utf8")).split(` +`}var Cl=class{constructor(t=Ik.stdin,n=Ik.stdout){this._stdin=t,this._stdout=n,this._readBuffer=new Al,this._started=!1,this._ondata=o=>{this._readBuffer.append(o),this.processReadBuffer()},this._onerror=o=>{this.onerror?.(o)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(;;)try{let t=this._readBuffer.readMessage();if(t===null)break;this.onmessage?.(t)}catch(t){this.onerror?.(t)}}async close(){this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.listenerCount("data")===0&&this._stdin.pause(),this._readBuffer.clear(),this.onclose?.()}send(t){return new Promise(n=>{let o=zk(t);this._stdout.write(o)?n():this._stdout.once("drain",n)})}};import{execFile as FN}from"node:child_process";import{readFile as jk,mkdtemp as JN,open as HN}from"node:fs/promises";import{join as Ul,dirname as KN}from"node:path";import{tmpdir as BN}from"node:os";import{existsSync as Ml}from"node:fs";var Ek="0.4.0",hg="5.0.12";function gg(e){return Number.parseInt(e,10)}async function Ok(){let e=await JN(Ul(BN(),"drywall-report-"));return{reportDir:e,reportPath:Ul(e,"jscpd-report.json")}}var GN=new Set(["jscpdVersion","respectGitignore","path","maxDuplicates","maxFragmentLength"]);function Pk(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}var WN=new Set(["ignore","ignorePattern","format"]);async function Nk(){try{let e=await jk(".drywallrc.json","utf8");return JSON.parse(e)}catch{return{}}}function Rk(e,t,n){let{jscpdVersion:o,respectGitignore:r,...i}=e,a=gg(o||hg),s={...i,...t},c=[];a>=5?r===!1&&c.push("--no-gitignore"):r!==!1&&c.push("--gitignore");for(let[u,l]of Object.entries(s)){if(GN.has(u))continue;if(u==="reporters")throw new Error('"reporters" is not configurable in DRYwall; it always uses the json reporter that the server reads. Remove it from your config.');let d=`--${Pk(u)}`;if(Array.isArray(l)){if(!WN.has(u))throw new Error(`Config key "${u}" does not accept multiple values; jscpd's --${Pk(u)} takes a single value. Provide a string, not an array.`);c.push(d,l.map(String).join(","))}else typeof l=="boolean"?l&&c.push(d):l!=null&&c.push(d,String(l))}return c.push("--reporters","json","--output",n),c}function Dk(e){return process.platform==="win32"&&typeof e=="string"?e.replace(/\\/g,"/"):e}var XN=/^\d+\.\d+\.\d+(-[\w.]+)?$/;function YN(e){if(process.platform!=="win32")return{command:"npx",spawnArgs:e,options:{}};let t=Ul(KN(process.execPath),"node_modules","npm","bin","npx-cli.js");return Ml(t)?{command:process.execPath,spawnArgs:[t,...e],options:{}}:{command:"npx.cmd",spawnArgs:e,options:{shell:!0}}}function Zk(e,t,n){if(!XN.test(e))throw new Error(`Invalid jscpd version: "${e}"`);let o=[`jscpd@${e}`,...t],r=["npx",...o],{command:i,spawnArgs:a,options:s}=YN(o);return new Promise((c,u)=>{FN(i,a,s,(l,d,p)=>{let f=n&&Ml(n)||p.includes("Clone found");l&&!f?u(new Error(p||l.message)):c({cmd:r,stdout:d,stderr:p})})})}var vg=20,yg=500;function Tk(e,t){if(!t||Ml(e))return e;let n=Ul(t,e);return Ml(n)?n:e}async function QN(e,t,n,o){let r;try{let i=Math.min(n-t,o*4+4);if(i<=0)return"";r=await HN(e,"r");let a=Buffer.alloc(i),{bytesRead:s}=await r.read(a,0,i,t);return a.toString("utf8",0,s)}catch{return""}finally{await r?.close()}}async function e4(e,t,n,o){try{return o.has(e)||o.set(e,(await jk(e,"utf8")).split(` `)),o.get(e).slice(t-1,n).join(` `)}catch{return""}}async function Ak(e,{maxDuplicates:t,maxFragmentLength:n,scanPath:o,jscpdMajor:r=0}={}){let i=t??vg,a=n??yg,s=JSON.parse(e),c=(s.duplicates||[]).slice().sort((p,f)=>f.lines-p.lines).slice(0,i),u=new Map,l=[];for(let p of c){let f={firstFile:Tk(p.firstFile.name,o),firstStart:p.firstFile.startLoc.line,firstEnd:p.firstFile.endLoc.line,secondFile:Tk(p.secondFile.name,o),secondStart:p.secondFile.startLoc.line,secondEnd:p.secondFile.endLoc.line,lines:p.lines,fragment:p.fragment};if(!f.fragment){let h=p.firstFile.startLoc.position,y=p.firstFile.endLoc.position;r>=5&&Number.isInteger(h)&&Number.isInteger(y)&&(f.fragment=await QN(f.firstFile,h,y,a)),f.fragment||(f.fragment=await e4(f.firstFile,f.firstStart,f.firstEnd,u))}f.fragment&&f.fragment.length>a&&(f.fragment=f.fragment.slice(0,a)+` [...truncated]`),l.push(f)}let d=s.statistics?.total||{};return{summary:{clones:d.clones||0,duplicatedLines:d.duplicatedLines||0,percentage:d.percentage||0,totalLines:d.lines||0},duplicates:l}}var Ck=new Zl({name:"drywall",version:Ek});Ck.registerTool("detect_code_duplication",{description:"Scan the codebase for duplicated code blocks using jscpd. Use this when the user asks about refactoring, deduplication, code consolidation, or reducing repetition in their codebase.",inputSchema:Ft.object({path:Ft.string().describe("Directory to scan. Defaults to current working directory.").optional(),options:Ft.looseObject({}).describe('jscpd options passed as CLI flags. Keys are camelCase and converted to --kebab-case flags. Examples: {"minTokens": 30, "minLines": 5, "ignore": ["**/test/**"], "format": ["javascript", "typescript"], "threshold": 10}. See https://jscpd.dev/getting-started/configuration#cli-options for all options.').optional(),maxDuplicates:Ft.number().int().describe(`Maximum number of duplicate pairs to return, ranked by impact. Defaults to ${vg}.`).optional(),maxFragmentLength:Ft.number().int().describe(`Maximum character length of each code fragment before truncation. Defaults to ${yg}.`).optional()})},async({path:e,options:t={},maxDuplicates:n,maxFragmentLength:o})=>{try{let r=await Nk(),i=r.jscpdVersion||hg,{reportDir:a,reportPath:s}=await Ok(),c=Rk(r,t,a),u=Dk(e||r.path||".");c.push(u);let{cmd:l}=await Zk(i,c,s),d=await t4(s,"utf8"),p=await Ak(d,{maxDuplicates:n??r.maxDuplicates,maxFragmentLength:o??r.maxFragmentLength,scanPath:u,jscpdMajor:gg(i)});return{content:[{type:"text",text:JSON.stringify({status:"ok",command:l.join(" "),cwd:process.cwd(),...p},null,2)}]}}catch(r){return{content:[{type:"text",text:JSON.stringify({status:"error",message:r.message},null,2)}],isError:!0}}});async function r4(){let e=new Cl;await Ck.connect(e)}r4().catch(console.error); diff --git a/test/fixtures/README.md b/test/fixtures/README.md index 1fe1ced..a932e76 100644 --- a/test/fixtures/README.md +++ b/test/fixtures/README.md @@ -20,7 +20,7 @@ cd test/fixtures # then invoke /drywall:scan in a Claude Code session # Or run jscpd directly -npx jscpd@4.2.5 --reporters json --output /tmp/drywall-report --min-tokens 30 --min-lines 5 src/ +npx jscpd@5.0.12 --reporters json --output /tmp/drywall-report --min-tokens 30 --min-lines 5 src/ cat /tmp/drywall-report/jscpd-report.json # Test the agent