"use strict";const y=require("./telemetry-C8yrvnwb.cjs"),c=require("./logger-BN0ZR9CS.cjs"),E=require("./shared-types-B8BH5zz1.cjs"),C=require("./model-provider-TqxgiEyN.cjs"),L=require("./stream-BfNQDS2Z.cjs");require("./base-DYJSEa-Z.cjs");require("uuid");require("./string-CNIv5GMJ.cjs");const T=require("./token-estimator-7OLZJiZ7.cjs"),_=require("./model-config-Clqxmxf5.cjs");var b=Object.defineProperty,O=Object.getOwnPropertyDescriptor,M=(g,s,e,i)=>{for(var t=O(s,e),a=g.length-1,o;a>=0;a--)(o=g[a])&&(t=o(s,e,t)||t);return t&&b(s,e,t),t};const R="qdev",N="CLAUDE_HAIKU_4_5_20251001_V1_0";class h extends Error{constructor(s,e){super(e),this.errorType=s,this.name="PruningError"}}var k=(g=>(g.Code="code",g.ShellOutput="shell_output",g.DirectoryListing="directory_listing",g.SearchResults="search_results",g.PlainText="plain_text",g))(k||{});class ${static MIN_TOKENS_FOR_PRUNING=1250;static pruningMetrics=y.getMetricReporterOrNoOp(E.TelemetryNamespace.Agent,"PruningService");static isPruningEnabled(){return _.isExperimentsFeatureEnabled("filePruning")}static async pruneContent(s){const{content:e,contentType:i,contextIdentifier:t,pruningReasoning:a,signal:o,skipPruning:n}=s,r=e.length;if(n)return c.logger.info(`[PruningService] [${i}] ${t} skipped (skipPruning flag set)`),this.pruningMetrics.reportCountMetrics({PruningSkipped:1},{ContentType:i,SkipReason:"flag"}),{prunedContent:e,originalLength:r,prunedLength:r,originalTokens:0,prunedTokens:0,wasPruned:!1,reductionPercentage:0,skipReason:"disabled"};if(!this.isPruningEnabled())return c.logger.debug(`[PruningService] [${i}] ${t} skipped (feature disabled)`),this.pruningMetrics.reportCountMetrics({PruningSkipped:1},{ContentType:i,SkipReason:"feature_disabled"}),{prunedContent:e,originalLength:r,prunedLength:r,originalTokens:0,prunedTokens:0,wasPruned:!1,reductionPercentage:0,skipReason:"disabled"};const f=`${R}::${N}`,S=new T.TokenEstimator,u=S.estimateTokens(e,f);if(c.logger.info(`[PruningService] [${i}] Processing ${t}, tokens: ${u} (${r} chars)`),u<this.MIN_TOKENS_FOR_PRUNING)return c.logger.info(`[PruningService] [${i}] ${t} is below ${this.MIN_TOKENS_FOR_PRUNING} tokens, skipping`),this.pruningMetrics.reportCountMetrics({PruningSkipped:1},{ContentType:i,SkipReason:"below_threshold"}),{prunedContent:e,originalLength:r,prunedLength:r,originalTokens:u,prunedTokens:u,wasPruned:!1,reductionPercentage:0,skipReason:"below_threshold"};try{const l=C.loadModel(R,N,"vibe"),P=this.createPruningPrompt(e,i,t,a),{lineRanges:d,rawResponse:I}=await this.invokeModelForLineRanges(l,P,i,o);if(d.length===0)throw new h("NoLineRanges","No valid line ranges returned from LLM");c.logger.info(`[PruningService] [${i}] Extracted ${d.length} line ranges for ${t}`),this.pruningMetrics.reportCountMetrics({LineRangeCount:d.length});const m=this.extractLineRanges(e,d,i),w=m.length,p=S.estimateTokens(m,f),v=u>0?(u-p)/u*100:0;return c.logger.info(`[PruningService] [${i}] Pruned ${t}: ${u} -> ${p} tokens (${v.toFixed(1)}% reduction)`),p>=u?(c.logger.warn(`[PruningService] [${i}] Pruning increased size for ${t} (${u} -> ${p} tokens, ${d.length} ranges). Returning original content. LLM response:
${I}`),this.pruningMetrics.reportCountMetrics({PruningNegativeReduction:1},{ContentType:i,RangeCount:String(d.length)}),{prunedContent:e,originalLength:r,prunedLength:r,originalTokens:u,prunedTokens:u,wasPruned:!1,reductionPercentage:0,skipReason:"error"}):(this.reportSuccessMetrics(v,t,u,p,i),{prunedContent:m,originalLength:r,prunedLength:w,originalTokens:u,prunedTokens:p,wasPruned:!0,reductionPercentage:v})}catch(l){const P=l instanceof h?l.errorType:l instanceof Error?l.constructor.name:"UnknownError",d=l instanceof Error?l.message:String(l);return c.logger.error(`[PruningService] [${i}] Error pruning ${t}: ${d}`,l),this.pruningMetrics.reportCountMetrics({PruningFailure:1},{FailureReason:P,ContentType:i}),{prunedContent:e,originalLength:r,prunedLength:r,originalTokens:u,prunedTokens:u,wasPruned:!1,reductionPercentage:0,skipReason:"error"}}}static reportSuccessMetrics(s,e,i,t,a){try{this.pruningMetrics.reportCountMetrics({PruningSuccess:1,TokenReductionPercentage:s,TokensPruned:i-t,OriginalTokens:i,PrunedTokens:t},{ContentType:a});const o=this.getTokenSizeCategory(i);if(this.pruningMetrics.reportCountMetrics({[`TokenReduction_${o}`]:s,[`TokenSize_${o}`]:1}),s<10&&this.pruningMetrics.reportCountMetrics({PruningLowEffectiveness:1,ZeroTokenReductionPercentage:s},{ContentType:a}),a==="code"){const n=this.getFileExtension(e);n&&this.pruningMetrics.reportCountMetrics({[`FileType_${n}`]:1})}}catch(o){c.logger.debug("[PruningService] Failed to report success metrics:",o)}}static getTokenSizeCategory(s){return s<2500?"small":s<12500?"medium":s<5e4?"large":"extra_large"}static getFileExtension(s){const e=s.match(/\.([^.]+)$/);return e?e[1].toLowerCase():null}static async invokeModelForLineRanges(s,e,i,t){const a=new L.HumanMessage({content:e}),o=await s.invoke([a],{signal:t}),n=typeof o.content=="string"?o.content:"";return{lineRanges:this.parseLineRanges(n,i),rawResponse:n}}static createPruningPrompt(s,e,i,t){const a=s.split(`
`),o=a.map((r,f)=>`${(f+1).toString().padStart(5," ")} | ${r}`).join(`
`);return`You are helping to optimize context for an AI agent. Your task is to identify which line ranges to preserve from the following content based on the reasoning provided.

IMPORTANT: You must respond with ONLY a valid JSON array of line ranges. Do not include any explanatory text before or after the JSON.

${this.getContentTypeGuidelines(e)}

OUTPUT FORMAT:
Respond with a JSON array of objects, each with "start" and "end" properties (and optionally "reason"):
[
  {"start": 1, "end": 25, "reason": "relevant section"},
  {"start": 50, "end": 100, "reason": "important content"}
]

Line numbers are 1-indexed and inclusive (both start and end are included).
Ranges should be in ascending order and non-overlapping.
If the entire content seems relevant, return a single range covering all lines.

PRUNING REASONING:
${t}

CONTENT TYPE: ${e}
CONTEXT: ${i}
Total lines: ${a.length}

${o}`}static getContentTypeGuidelines(s){switch(s){case"code":return`PRUNING GUIDELINES:
1. Identify line ranges that are directly relevant to the current task
2. Preserve important structural elements (class definitions, key interfaces, main functions)
3. For large methods, you can include just the signature lines if not directly relevant
4. Include enough context around relevant sections to maintain code coherence`;case"shell_output":return`PRUNING GUIDELINES:
1. Identify line ranges containing errors, warnings, stack traces, or exit codes - these are critical
2. Include the first few lines showing the command and initial output for context
3. Include the final lines showing completion status or summary
4. You can omit repetitive log entries, progress indicators, or verbose output in the middle`;case"directory_listing":return`PRUNING GUIDELINES:
1. Identify line ranges for directories and files relevant to the current task
2. Include parent directory lines to preserve hierarchy context
3. You can omit contents of node_modules, build output, or cache directories
4. Prioritize source directories, configuration files, and entry points`;case"search_results":return`PRUNING GUIDELINES:
1. Identify line ranges for search matches most relevant to the current task
2. Keep file path headers together with their matches (they span multiple lines)
3. You can omit matches in node_modules, generated files, or vendored code
4. Prioritize unique matches over duplicates showing the same pattern`;default:return`PRUNING GUIDELINES:
1. Identify line ranges containing information directly relevant to the current task
2. Preserve section headers and structural markers for context
3. You can omit repetitive content or verbose explanations
4. Include introductory and concluding sections if they provide useful context`}}static extractLineRanges(s,e,i){const t=s.split(`
`),a=[];let o=0;for(const n of e){if(n.start<1||n.end>t.length||n.start>n.end){c.logger.warn(`[PruningService] [${i}] Invalid line range: ${n.start}-${n.end} (content has ${t.length} lines), skipping`),o++;continue}const r=t.slice(n.start-1,n.end).join(`
`);a.push(r)}return o>0&&this.pruningMetrics.reportCountMetrics({LineRangeError:o}),a.join(`

⋮ [content omitted by pruning]

`)}static parseLineRanges(s,e){if(!s||typeof s!="string")throw c.logger.warn(`[PruningService] [${e}] Empty or invalid response from LLM`),this.pruningMetrics.reportCountMetrics({LineRangeParseError:1}),new h("EmptyLLMResponse","Empty or invalid response from LLM");const i=s.match(/\[[\s\S]*\]/);if(!i){const n=s.substring(0,200);throw c.logger.warn(`[PruningService] [${e}] No JSON array found in response: ${n}...`),this.pruningMetrics.reportCountMetrics({LineRangeParseError:1}),new h("NoJsonArray",`No JSON array found in response: ${n}`)}let t;try{t=JSON.parse(i[0])}catch(n){const r=n instanceof Error?n.message:String(n);throw c.logger.warn(`[PruningService] [${e}] JSON parse error: ${r}, content: ${i[0].substring(0,200)}...`),this.pruningMetrics.reportCountMetrics({LineRangeParseError:1}),new h("InvalidJson",`Invalid JSON in response: ${r}`)}if(!Array.isArray(t)){const n=typeof t;throw c.logger.warn(`[PruningService] [${e}] Response is not an array: ${n}`),this.pruningMetrics.reportCountMetrics({LineRangeParseError:1}),new h("ResponseNotArray",`Response is not an array, got: ${n}`)}const a=[];let o=0;for(const n of t){if(!n||typeof n!="object"){c.logger.warn(`[PruningService] [${e}] Invalid item type: ${typeof n}, skipping`),o++;continue}const r=n;if(typeof r.start!="number"||typeof r.end!="number"){c.logger.warn(`[PruningService] [${e}] Invalid range format: ${JSON.stringify(n)}, skipping`),o++;continue}if(r.start<1||r.end<1||!Number.isInteger(r.start)||!Number.isInteger(r.end)){c.logger.warn(`[PruningService] [${e}] Invalid range values: start=${r.start}, end=${r.end}, skipping`),o++;continue}a.push({start:r.start,end:r.end,reason:typeof r.reason=="string"?r.reason:void 0})}return o>0&&this.pruningMetrics.reportCountMetrics({LineRangeFormatError:o}),a.sort((n,r)=>n.start-r.start),c.logger.debug(`[PruningService] [${e}] Successfully parsed ${a.length} line ranges`),a}}M([y.Telemetry.Trace("PruningService.PruneContent")],$,"pruneContent");M([y.Telemetry.Trace("PruningService.InvokePruningModel")],$,"invokeModelForLineRanges");exports.ContentType=k;exports.PruningService=$;
//# sourceMappingURL=pruning-service-DXWqhVdA.cjs.map
