33 * Provides call graph queries via the dev_refs tool
44 */
55
6- import type { CalleeInfo , SearchResult , SearchService } from '@prosdevlab/dev-agent-core' ;
6+ import type {
7+ CalleeInfo ,
8+ RepositoryIndexer ,
9+ SearchResult ,
10+ SearchService ,
11+ } from '@prosdevlab/dev-agent-core' ;
12+ import { buildDependencyGraph , shortestPath } from '@prosdevlab/dev-agent-core' ;
713import { estimateTokensForText , startTimer } from '../../formatters/utils' ;
814import { RefsArgsSchema } from '../../schemas/index.js' ;
915import { ToolAdapter } from '../tool-adapter' ;
@@ -24,6 +30,11 @@ export interface RefsAdapterConfig {
2430 */
2531 searchService : SearchService ;
2632
33+ /**
34+ * Repository indexer — needed for path tracing (optional)
35+ */
36+ indexer ?: RepositoryIndexer ;
37+
2738 /**
2839 * Default result limit
2940 */
@@ -54,13 +65,17 @@ export class RefsAdapter extends ToolAdapter {
5465 } ;
5566
5667 private searchService : SearchService ;
57- private config : Required < Omit < RefsAdapterConfig , 'searchService' > > & {
68+ private config : {
5869 searchService : SearchService ;
70+ defaultLimit : number ;
5971 } ;
6072
73+ private indexer ?: RepositoryIndexer ;
74+
6175 constructor ( config : RefsAdapterConfig ) {
6276 super ( ) ;
6377 this . searchService = config . searchService ;
78+ this . indexer = config . indexer ;
6479 this . config = {
6580 searchService : config . searchService ,
6681 defaultLimit : config . defaultLimit ?? 20 ,
@@ -101,6 +116,12 @@ export class RefsAdapter extends ToolAdapter {
101116 maximum : 50 ,
102117 default : this . config . defaultLimit ,
103118 } ,
119+ traceTo : {
120+ type : 'string' ,
121+ description :
122+ "Trace the dependency chain from this function's file to a target file " +
123+ '(e.g., "src/database.ts"). Shows the shortest path through the call graph.' ,
124+ } ,
104125 } ,
105126 required : [ 'name' ] ,
106127 } ,
@@ -114,11 +135,11 @@ export class RefsAdapter extends ToolAdapter {
114135 return validation . error ;
115136 }
116137
117- const { name, direction, limit } = validation . data ;
138+ const { name, direction, limit, traceTo } = validation . data ;
118139
119140 try {
120141 const timer = startTimer ( ) ;
121- context . logger . debug ( 'Executing refs query' , { name, direction, limit } ) ;
142+ context . logger . debug ( 'Executing refs query' , { name, direction, limit, traceTo } ) ;
122143
123144 // First, find the target component
124145 const searchResults = await this . searchService . search ( name , { limit : 10 } ) ;
@@ -136,6 +157,29 @@ export class RefsAdapter extends ToolAdapter {
136157 } ;
137158 }
138159
160+ // Handle traceTo — find shortest dependency path
161+ if ( traceTo && this . indexer ) {
162+ const sourceFile = ( target . metadata . path as string ) || '' ;
163+ const allDocs = await this . indexer . getAll ( { limit : 10000 } ) ;
164+ const graph = buildDependencyGraph ( allDocs ) ;
165+ const path = shortestPath ( graph , sourceFile , traceTo ) ;
166+
167+ const content = path
168+ ? `## Dependency Path: ${ sourceFile } → ${ traceTo } \n\n${ path . join ( ' → ' ) } \n\n**${ path . length - 1 } hop${ path . length - 1 === 1 ? '' : 's' } **`
169+ : `## No Path Found\n\nNo dependency chain from \`${ sourceFile } \` to \`${ traceTo } \`.\nThese files may be in separate subsystems.` ;
170+
171+ return {
172+ success : true ,
173+ data : content ,
174+ metadata : {
175+ tokens : estimateTokensForText ( content ) ,
176+ duration_ms : timer . elapsed ( ) ,
177+ timestamp : new Date ( ) . toISOString ( ) ,
178+ cached : false ,
179+ } ,
180+ } ;
181+ }
182+
139183 const result : {
140184 target : {
141185 name : string ;
0 commit comments