refactor: codebase audit cleanup — dead code, dedup, module splits
Multi-agent audit + aggressive cleanup across server/web/coder/booterm, delivered behind a DEFER discipline so none of the in-flight files were touched. Removes dead code/deps/columns, dedups server + coder helpers, and splits the oversized modules (tools.ts, opencode-server.ts, sentinel-summaries, turn.ts, TerminalPane.tsx) behind stable contracts. Adds 78 parity/unit tests (server 587, coder 323); fixes two latent bugs (ChatPane queue keys, FileViewerOverlay blank-line parity). Intended tag: v2.7.12-audit-cleanup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
43
apps/server/src/services/tools/codecontext/factory.ts
Normal file
43
apps/server/src/services/tools/codecontext/factory.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../types.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
|
||||
// Shared factory for the 12 codecontext shim ToolDefs.
|
||||
// Each shim provides name/schema/description/jsonParameters/mapArgs; the
|
||||
// factory builds the ToolDef and returns both the ToolDef and the standalone
|
||||
// execute function (used by tests that inject a custom fetcher).
|
||||
export function makeCodecontextTool<TInput>(opts: {
|
||||
name: string;
|
||||
schema: z.ZodType<TInput>;
|
||||
description: string;
|
||||
jsonParameters: Record<string, unknown>;
|
||||
mapArgs: (input: TInput) => Record<string, unknown>;
|
||||
}): {
|
||||
toolDef: ToolDef<TInput>;
|
||||
execute: (input: TInput, projectPath: string, fetcher?: typeof fetch) => Promise<CodecontextResponse>;
|
||||
} {
|
||||
const { name, schema, description, jsonParameters, mapArgs } = opts;
|
||||
|
||||
async function execute(
|
||||
input: TInput,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
return callCodecontext({ toolName: name, args: mapArgs(input), projectPath }, fetcher);
|
||||
}
|
||||
|
||||
const toolDef: ToolDef<TInput> = {
|
||||
name,
|
||||
description,
|
||||
inputSchema: schema,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: { name, description, parameters: jsonParameters },
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return execute(input, projectRoot);
|
||||
},
|
||||
};
|
||||
|
||||
return { toolDef, execute };
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const GetBlastRadiusInput = z.object({
|
||||
file_path: z.string().trim().min(1),
|
||||
@@ -12,40 +11,23 @@ const DESCRIPTION =
|
||||
'Use to assess the impact of changing a file — "what breaks if I modify this?" ' +
|
||||
'Traverses the import graph in reverse via BFS. Results sorted by distance (closest dependents first).';
|
||||
|
||||
export async function executeGetBlastRadius(
|
||||
input: GetBlastRadiusInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
return callCodecontext(
|
||||
{ toolName: 'get_blast_radius', args: { file_path: input.file_path }, projectPath },
|
||||
fetcher,
|
||||
);
|
||||
}
|
||||
|
||||
export const getBlastRadius: ToolDef<GetBlastRadiusInputT> = {
|
||||
name: 'get_blast_radius',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: GetBlastRadiusInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'get_blast_radius',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
file_path: {
|
||||
type: 'string',
|
||||
description: 'Absolute or project-relative path to the file to analyze.',
|
||||
},
|
||||
const { toolDef: getBlastRadius, execute: executeGetBlastRadius } =
|
||||
makeCodecontextTool<GetBlastRadiusInputT>({
|
||||
name: 'get_blast_radius',
|
||||
schema: GetBlastRadiusInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
file_path: {
|
||||
type: 'string',
|
||||
description: 'Absolute or project-relative path to the file to analyze.',
|
||||
},
|
||||
required: ['file_path'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
required: ['file_path'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeGetBlastRadius(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: (input) => ({ file_path: input.file_path }),
|
||||
});
|
||||
|
||||
export { getBlastRadius, executeGetBlastRadius };
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
// v1.12 Track B.2: codecontext wrapper — get_codebase_overview.
|
||||
// Pattern mirrors services/web_search.ts: pure executor + ToolDef wrapper.
|
||||
// target_dir is supplied by callCodecontext from the resolved project root.
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const GetCodebaseOverviewInput = z.object({
|
||||
include_stats: z.boolean().optional(),
|
||||
@@ -17,43 +12,22 @@ const DESCRIPTION =
|
||||
'Tree-sitter coverage: full for JS/Python/Java/Go/Rust/C++. TypeScript symbols are approximate (uses JS grammar). ' +
|
||||
'PHP and SQL are not supported — fall back to view_file/grep for those.';
|
||||
|
||||
export async function executeGetCodebaseOverview(
|
||||
input: GetCodebaseOverviewInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
return callCodecontext(
|
||||
{
|
||||
toolName: 'get_codebase_overview',
|
||||
args: { include_stats: input.include_stats ?? true },
|
||||
projectPath,
|
||||
},
|
||||
fetcher,
|
||||
);
|
||||
}
|
||||
|
||||
export const getCodebaseOverview: ToolDef<GetCodebaseOverviewInputT> = {
|
||||
name: 'get_codebase_overview',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: GetCodebaseOverviewInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'get_codebase_overview',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
include_stats: {
|
||||
type: 'boolean',
|
||||
description: 'Include file count, symbol count, language stats. Defaults to true.',
|
||||
},
|
||||
const { toolDef: getCodebaseOverview, execute: executeGetCodebaseOverview } =
|
||||
makeCodecontextTool<GetCodebaseOverviewInputT>({
|
||||
name: 'get_codebase_overview',
|
||||
schema: GetCodebaseOverviewInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
include_stats: {
|
||||
type: 'boolean',
|
||||
description: 'Include file count, symbol count, language stats. Defaults to true.',
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeGetCodebaseOverview(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: (input) => ({ include_stats: input.include_stats ?? true }),
|
||||
});
|
||||
|
||||
export { getCodebaseOverview, executeGetCodebaseOverview };
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// v1.12 Track B.2: codecontext wrapper — get_dependencies.
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const GetDependenciesInput = z.object({
|
||||
file_path: z.string().trim().optional(),
|
||||
@@ -16,45 +13,31 @@ const DESCRIPTION =
|
||||
'Tree-sitter coverage: full for JS/Python/Java/Go/Rust/C++. TypeScript dependencies are approximate. ' +
|
||||
'PHP and SQL are not supported.';
|
||||
|
||||
export async function executeGetDependencies(
|
||||
input: GetDependenciesInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
const args: Record<string, unknown> = {
|
||||
direction: input.direction ?? 'both',
|
||||
};
|
||||
if (input.file_path) args['file_path'] = input.file_path;
|
||||
return callCodecontext({ toolName: 'get_dependencies', args, projectPath }, fetcher);
|
||||
}
|
||||
|
||||
export const getDependencies: ToolDef<GetDependenciesInputT> = {
|
||||
name: 'get_dependencies',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: GetDependenciesInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'get_dependencies',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
file_path: {
|
||||
type: 'string',
|
||||
description: 'Narrow to a single file. Omit for a project-wide graph.',
|
||||
},
|
||||
direction: {
|
||||
type: 'string',
|
||||
enum: ['incoming', 'outgoing', 'both'],
|
||||
description: 'Which edges to include. Defaults to "both".',
|
||||
},
|
||||
const { toolDef: getDependencies, execute: executeGetDependencies } =
|
||||
makeCodecontextTool<GetDependenciesInputT>({
|
||||
name: 'get_dependencies',
|
||||
schema: GetDependenciesInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
file_path: {
|
||||
type: 'string',
|
||||
description: 'Narrow to a single file. Omit for a project-wide graph.',
|
||||
},
|
||||
direction: {
|
||||
type: 'string',
|
||||
enum: ['incoming', 'outgoing', 'both'],
|
||||
description: 'Which edges to include. Defaults to "both".',
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeGetDependencies(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: (input) => {
|
||||
const args: Record<string, unknown> = { direction: input.direction ?? 'both' };
|
||||
if (input.file_path) args['file_path'] = input.file_path;
|
||||
return args;
|
||||
},
|
||||
});
|
||||
|
||||
export { getDependencies, executeGetDependencies };
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// v1.12 Track B.2: codecontext wrapper — get_file_analysis.
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const GetFileAnalysisInput = z.object({
|
||||
file_path: z.string().trim().min(1),
|
||||
@@ -15,44 +12,23 @@ const DESCRIPTION =
|
||||
'Tree-sitter coverage: full for JS/Python/Java/Go/Rust/C++. TypeScript symbols are approximate. ' +
|
||||
'PHP and SQL are not supported — fall back to view_file for those.';
|
||||
|
||||
export async function executeGetFileAnalysis(
|
||||
input: GetFileAnalysisInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
return callCodecontext(
|
||||
{
|
||||
toolName: 'get_file_analysis',
|
||||
args: { file_path: input.file_path },
|
||||
projectPath,
|
||||
},
|
||||
fetcher,
|
||||
);
|
||||
}
|
||||
|
||||
export const getFileAnalysis: ToolDef<GetFileAnalysisInputT> = {
|
||||
name: 'get_file_analysis',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: GetFileAnalysisInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'get_file_analysis',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
file_path: {
|
||||
type: 'string',
|
||||
description: 'Absolute or project-relative path to the file.',
|
||||
},
|
||||
const { toolDef: getFileAnalysis, execute: executeGetFileAnalysis } =
|
||||
makeCodecontextTool<GetFileAnalysisInputT>({
|
||||
name: 'get_file_analysis',
|
||||
schema: GetFileAnalysisInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
file_path: {
|
||||
type: 'string',
|
||||
description: 'Absolute or project-relative path to the file.',
|
||||
},
|
||||
required: ['file_path'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
required: ['file_path'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeGetFileAnalysis(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: (input) => ({ file_path: input.file_path }),
|
||||
});
|
||||
|
||||
export { getFileAnalysis, executeGetFileAnalysis };
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// v1.12 Track B.2: codecontext wrapper — get_framework_analysis.
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const GetFrameworkAnalysisInput = z.object({
|
||||
framework: z.string().optional(),
|
||||
@@ -16,43 +13,31 @@ const DESCRIPTION =
|
||||
'Tree-sitter coverage: full for JS/Python/Java/Go/Rust/C++. TypeScript is approximate. ' +
|
||||
'PHP and SQL are not supported.';
|
||||
|
||||
export async function executeGetFrameworkAnalysis(
|
||||
input: GetFrameworkAnalysisInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
const args: Record<string, unknown> = {};
|
||||
if (input.framework) args['framework'] = input.framework;
|
||||
if (input.include_stats !== undefined) args['include_stats'] = input.include_stats;
|
||||
return callCodecontext({ toolName: 'get_framework_analysis', args, projectPath }, fetcher);
|
||||
}
|
||||
|
||||
export const getFrameworkAnalysis: ToolDef<GetFrameworkAnalysisInputT> = {
|
||||
name: 'get_framework_analysis',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: GetFrameworkAnalysisInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'get_framework_analysis',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
framework: {
|
||||
type: 'string',
|
||||
description: 'Framework name. Auto-detected if omitted.',
|
||||
},
|
||||
include_stats: {
|
||||
type: 'boolean',
|
||||
description: 'Include component/hook/service counts.',
|
||||
},
|
||||
const { toolDef: getFrameworkAnalysis, execute: executeGetFrameworkAnalysis } =
|
||||
makeCodecontextTool<GetFrameworkAnalysisInputT>({
|
||||
name: 'get_framework_analysis',
|
||||
schema: GetFrameworkAnalysisInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
framework: {
|
||||
type: 'string',
|
||||
description: 'Framework name. Auto-detected if omitted.',
|
||||
},
|
||||
include_stats: {
|
||||
type: 'boolean',
|
||||
description: 'Include component/hook/service counts.',
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeGetFrameworkAnalysis(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: (input) => {
|
||||
const args: Record<string, unknown> = {};
|
||||
if (input.framework) args['framework'] = input.framework;
|
||||
if (input.include_stats !== undefined) args['include_stats'] = input.include_stats;
|
||||
return args;
|
||||
},
|
||||
});
|
||||
|
||||
export { getFrameworkAnalysis, executeGetFrameworkAnalysis };
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const GetHotFilesInput = z.object({
|
||||
limit: z.number().int().min(1).max(100).optional(),
|
||||
@@ -12,39 +11,22 @@ const DESCRIPTION =
|
||||
'Hot files are high-risk change targets — many other files depend on them. ' +
|
||||
'Use to identify core modules and assess refactoring risk.';
|
||||
|
||||
export async function executeGetHotFiles(
|
||||
input: GetHotFilesInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
return callCodecontext(
|
||||
{ toolName: 'get_hot_files', args: input.limit != null ? { limit: input.limit } : {}, projectPath },
|
||||
fetcher,
|
||||
);
|
||||
}
|
||||
|
||||
export const getHotFiles: ToolDef<GetHotFilesInputT> = {
|
||||
name: 'get_hot_files',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: GetHotFilesInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'get_hot_files',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
limit: {
|
||||
type: 'number',
|
||||
description: 'Maximum number of files to return (default 20, max 100).',
|
||||
},
|
||||
const { toolDef: getHotFiles, execute: executeGetHotFiles } =
|
||||
makeCodecontextTool<GetHotFilesInputT>({
|
||||
name: 'get_hot_files',
|
||||
schema: GetHotFilesInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
limit: {
|
||||
type: 'number',
|
||||
description: 'Maximum number of files to return (default 20, max 100).',
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeGetHotFiles(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: (input) => (input.limit != null ? { limit: input.limit } : {}),
|
||||
});
|
||||
|
||||
export { getHotFiles, executeGetHotFiles };
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const GetMiddlewareInput = z.object({});
|
||||
export type GetMiddlewareInputT = z.infer<typeof GetMiddlewareInput>;
|
||||
@@ -11,31 +10,17 @@ const DESCRIPTION =
|
||||
'import names (@fastify/cors, helmet, etc.) and registration patterns ' +
|
||||
'(app.register, app.addHook, app.setErrorHandler).';
|
||||
|
||||
export async function executeGetMiddleware(
|
||||
_input: GetMiddlewareInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
return callCodecontext({ toolName: 'get_middleware', args: {}, projectPath }, fetcher);
|
||||
}
|
||||
|
||||
export const getMiddleware: ToolDef<GetMiddlewareInputT> = {
|
||||
name: 'get_middleware',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: GetMiddlewareInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'get_middleware',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
additionalProperties: false,
|
||||
},
|
||||
const { toolDef: getMiddleware, execute: executeGetMiddleware } =
|
||||
makeCodecontextTool<GetMiddlewareInputT>({
|
||||
name: 'get_middleware',
|
||||
schema: GetMiddlewareInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeGetMiddleware(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: () => ({}),
|
||||
});
|
||||
|
||||
export { getMiddleware, executeGetMiddleware };
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const GetRoutesInput = z.object({
|
||||
framework: z.string().trim().optional(),
|
||||
@@ -13,38 +12,26 @@ const DESCRIPTION =
|
||||
'with method, path, file, line number, and inferred tags (db, auth, cache). ' +
|
||||
'Optional framework filter narrows to "fastify" or "express".';
|
||||
|
||||
export async function executeGetRoutes(
|
||||
input: GetRoutesInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
const args: Record<string, unknown> = {};
|
||||
if (input.framework) args.framework = input.framework;
|
||||
return callCodecontext({ toolName: 'get_routes', args, projectPath }, fetcher);
|
||||
}
|
||||
|
||||
export const getRoutes: ToolDef<GetRoutesInputT> = {
|
||||
name: 'get_routes',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: GetRoutesInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'get_routes',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
framework: {
|
||||
type: 'string',
|
||||
description: 'Filter to a specific framework: "fastify" or "express". Omit for all.',
|
||||
},
|
||||
const { toolDef: getRoutes, execute: executeGetRoutes } =
|
||||
makeCodecontextTool<GetRoutesInputT>({
|
||||
name: 'get_routes',
|
||||
schema: GetRoutesInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
framework: {
|
||||
type: 'string',
|
||||
description: 'Filter to a specific framework: "fastify" or "express". Omit for all.',
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeGetRoutes(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: (input) => {
|
||||
const args: Record<string, unknown> = {};
|
||||
if (input.framework) args.framework = input.framework;
|
||||
return args;
|
||||
},
|
||||
});
|
||||
|
||||
export { getRoutes, executeGetRoutes };
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// v1.12 Track B.2: codecontext wrapper — get_semantic_neighborhoods.
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const GetSemanticNeighborhoodsInput = z.object({
|
||||
file_path: z.string().trim().optional(),
|
||||
@@ -20,54 +17,42 @@ const DESCRIPTION =
|
||||
|
||||
const DEFAULT_MAX_RESULTS = 10;
|
||||
|
||||
export async function executeGetSemanticNeighborhoods(
|
||||
input: GetSemanticNeighborhoodsInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
const args: Record<string, unknown> = {
|
||||
max_results: input.max_results ?? DEFAULT_MAX_RESULTS,
|
||||
};
|
||||
if (input.file_path) args['file_path'] = input.file_path;
|
||||
if (input.include_basic !== undefined) args['include_basic'] = input.include_basic;
|
||||
if (input.include_quality !== undefined) args['include_quality'] = input.include_quality;
|
||||
return callCodecontext({ toolName: 'get_semantic_neighborhoods', args, projectPath }, fetcher);
|
||||
}
|
||||
|
||||
export const getSemanticNeighborhoods: ToolDef<GetSemanticNeighborhoodsInputT> = {
|
||||
name: 'get_semantic_neighborhoods',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: GetSemanticNeighborhoodsInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'get_semantic_neighborhoods',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
file_path: {
|
||||
type: 'string',
|
||||
description: 'Anchor file for the neighborhood query. Omit for a project-wide view.',
|
||||
},
|
||||
include_basic: {
|
||||
type: 'boolean',
|
||||
description: 'Include the basic (import-based) neighborhood. Default true.',
|
||||
},
|
||||
include_quality: {
|
||||
type: 'boolean',
|
||||
description: 'Include code-quality metrics for the neighborhood. Default false.',
|
||||
},
|
||||
max_results: {
|
||||
type: 'integer',
|
||||
description: `Cap on neighborhoods returned. Defaults to ${DEFAULT_MAX_RESULTS}.`,
|
||||
},
|
||||
const { toolDef: getSemanticNeighborhoods, execute: executeGetSemanticNeighborhoods } =
|
||||
makeCodecontextTool<GetSemanticNeighborhoodsInputT>({
|
||||
name: 'get_semantic_neighborhoods',
|
||||
schema: GetSemanticNeighborhoodsInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
file_path: {
|
||||
type: 'string',
|
||||
description: 'Anchor file for the neighborhood query. Omit for a project-wide view.',
|
||||
},
|
||||
include_basic: {
|
||||
type: 'boolean',
|
||||
description: 'Include the basic (import-based) neighborhood. Default true.',
|
||||
},
|
||||
include_quality: {
|
||||
type: 'boolean',
|
||||
description: 'Include code-quality metrics for the neighborhood. Default false.',
|
||||
},
|
||||
max_results: {
|
||||
type: 'integer',
|
||||
description: `Cap on neighborhoods returned. Defaults to ${DEFAULT_MAX_RESULTS}.`,
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeGetSemanticNeighborhoods(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: (input) => {
|
||||
const args: Record<string, unknown> = {
|
||||
max_results: input.max_results ?? DEFAULT_MAX_RESULTS,
|
||||
};
|
||||
if (input.file_path) args['file_path'] = input.file_path;
|
||||
if (input.include_basic !== undefined) args['include_basic'] = input.include_basic;
|
||||
if (input.include_quality !== undefined) args['include_quality'] = input.include_quality;
|
||||
return args;
|
||||
},
|
||||
});
|
||||
|
||||
export { getSemanticNeighborhoods, executeGetSemanticNeighborhoods };
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// v1.12 Track B.2: codecontext wrapper — get_symbol_info.
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const GetSymbolInfoInput = z.object({
|
||||
symbol_name: z.string().min(1),
|
||||
@@ -16,48 +13,36 @@ const DESCRIPTION =
|
||||
'Tree-sitter coverage: full for JS/Python/Java/Go/Rust/C++. TypeScript symbols are approximate (uses JS grammar). ' +
|
||||
'PHP and SQL are not supported — fall back to grep for those.';
|
||||
|
||||
export async function executeGetSymbolInfo(
|
||||
input: GetSymbolInfoInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
const args: Record<string, unknown> = { symbol_name: input.symbol_name };
|
||||
if (input.file_path) args['file_path'] = input.file_path;
|
||||
if (input.framework_type) args['framework_type'] = input.framework_type;
|
||||
return callCodecontext({ toolName: 'get_symbol_info', args, projectPath }, fetcher);
|
||||
}
|
||||
|
||||
export const getSymbolInfo: ToolDef<GetSymbolInfoInputT> = {
|
||||
name: 'get_symbol_info',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: GetSymbolInfoInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'get_symbol_info',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
symbol_name: {
|
||||
type: 'string',
|
||||
description: 'The symbol name to look up (case-sensitive).',
|
||||
},
|
||||
file_path: {
|
||||
type: 'string',
|
||||
description: 'Narrow to a specific file when the symbol name is ambiguous.',
|
||||
},
|
||||
framework_type: {
|
||||
type: 'string',
|
||||
description: 'Hint for framework-specific extraction (react|vue|svelte|django|fastapi|express|nest|…).',
|
||||
},
|
||||
const { toolDef: getSymbolInfo, execute: executeGetSymbolInfo } =
|
||||
makeCodecontextTool<GetSymbolInfoInputT>({
|
||||
name: 'get_symbol_info',
|
||||
schema: GetSymbolInfoInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
symbol_name: {
|
||||
type: 'string',
|
||||
description: 'The symbol name to look up (case-sensitive).',
|
||||
},
|
||||
file_path: {
|
||||
type: 'string',
|
||||
description: 'Narrow to a specific file when the symbol name is ambiguous.',
|
||||
},
|
||||
framework_type: {
|
||||
type: 'string',
|
||||
description: 'Hint for framework-specific extraction (react|vue|svelte|django|fastapi|express|nest|…).',
|
||||
},
|
||||
required: ['symbol_name'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
required: ['symbol_name'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeGetSymbolInfo(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: (input) => {
|
||||
const args: Record<string, unknown> = { symbol_name: input.symbol_name };
|
||||
if (input.file_path) args['file_path'] = input.file_path;
|
||||
if (input.framework_type) args['framework_type'] = input.framework_type;
|
||||
return args;
|
||||
},
|
||||
});
|
||||
|
||||
export { getSymbolInfo, executeGetSymbolInfo };
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// v1.12 Track B.2: codecontext wrapper — search_symbols.
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const SearchSymbolsInput = z.object({
|
||||
query: z.string().min(1),
|
||||
@@ -21,57 +18,45 @@ const DESCRIPTION =
|
||||
|
||||
const DEFAULT_LIMIT = 20;
|
||||
|
||||
export async function executeSearchSymbols(
|
||||
input: SearchSymbolsInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
const args: Record<string, unknown> = {
|
||||
query: input.query,
|
||||
limit: input.limit ?? DEFAULT_LIMIT,
|
||||
};
|
||||
if (input.file_type) args['file_type'] = input.file_type;
|
||||
if (input.symbol_type) args['symbol_type'] = input.symbol_type;
|
||||
if (input.framework_type) args['framework_type'] = input.framework_type;
|
||||
return callCodecontext({ toolName: 'search_symbols', args, projectPath }, fetcher);
|
||||
}
|
||||
|
||||
export const searchSymbols: ToolDef<SearchSymbolsInputT> = {
|
||||
name: 'search_symbols',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: SearchSymbolsInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'search_symbols',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
query: { type: 'string', description: 'Substring or name fragment to match.' },
|
||||
file_type: {
|
||||
type: 'string',
|
||||
description: 'Filter by file extension or language (e.g. "ts", "py", "go").',
|
||||
},
|
||||
symbol_type: {
|
||||
type: 'string',
|
||||
description: 'Filter by kind: function|class|method|variable|type|interface.',
|
||||
},
|
||||
framework_type: {
|
||||
type: 'string',
|
||||
description: 'Filter by framework context (react|vue|svelte|…).',
|
||||
},
|
||||
limit: {
|
||||
type: 'integer',
|
||||
description: `Max matches to return. Defaults to ${DEFAULT_LIMIT}.`,
|
||||
},
|
||||
const { toolDef: searchSymbols, execute: executeSearchSymbols } =
|
||||
makeCodecontextTool<SearchSymbolsInputT>({
|
||||
name: 'search_symbols',
|
||||
schema: SearchSymbolsInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
query: { type: 'string', description: 'Substring or name fragment to match.' },
|
||||
file_type: {
|
||||
type: 'string',
|
||||
description: 'Filter by file extension or language (e.g. "ts", "py", "go").',
|
||||
},
|
||||
symbol_type: {
|
||||
type: 'string',
|
||||
description: 'Filter by kind: function|class|method|variable|type|interface.',
|
||||
},
|
||||
framework_type: {
|
||||
type: 'string',
|
||||
description: 'Filter by framework context (react|vue|svelte|…).',
|
||||
},
|
||||
limit: {
|
||||
type: 'integer',
|
||||
description: `Max matches to return. Defaults to ${DEFAULT_LIMIT}.`,
|
||||
},
|
||||
required: ['query'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
required: ['query'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeSearchSymbols(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: (input) => {
|
||||
const args: Record<string, unknown> = {
|
||||
query: input.query,
|
||||
limit: input.limit ?? DEFAULT_LIMIT,
|
||||
};
|
||||
if (input.file_type) args['file_type'] = input.file_type;
|
||||
if (input.symbol_type) args['symbol_type'] = input.symbol_type;
|
||||
if (input.framework_type) args['framework_type'] = input.framework_type;
|
||||
return args;
|
||||
},
|
||||
});
|
||||
|
||||
export { searchSymbols, executeSearchSymbols };
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// v1.12 Track B.2: codecontext wrapper — watch_changes.
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { ToolDef } from '../../tools.js';
|
||||
import { callCodecontext, type CodecontextResponse } from '../../codecontext_client.js';
|
||||
import { makeCodecontextTool } from './factory.js';
|
||||
|
||||
export const WatchChangesInput = z.object({
|
||||
enable: z.boolean(),
|
||||
@@ -10,48 +7,27 @@ export const WatchChangesInput = z.object({
|
||||
export type WatchChangesInputT = z.infer<typeof WatchChangesInput>;
|
||||
|
||||
const DESCRIPTION =
|
||||
'Turn codecontext\'s file watcher on or off for this project. ' +
|
||||
"Turn codecontext's file watcher on or off for this project. " +
|
||||
'When on, codecontext re-analyzes files in the background as they change (debounced). Default is on. ' +
|
||||
'Disable temporarily if you\'re doing bulk edits and want to avoid analysis churn.';
|
||||
"Disable temporarily if you're doing bulk edits and want to avoid analysis churn.";
|
||||
|
||||
export async function executeWatchChanges(
|
||||
input: WatchChangesInputT,
|
||||
projectPath: string,
|
||||
fetcher: typeof fetch = fetch,
|
||||
): Promise<CodecontextResponse> {
|
||||
return callCodecontext(
|
||||
{
|
||||
toolName: 'watch_changes',
|
||||
args: { enable: input.enable },
|
||||
projectPath,
|
||||
},
|
||||
fetcher,
|
||||
);
|
||||
}
|
||||
|
||||
export const watchChanges: ToolDef<WatchChangesInputT> = {
|
||||
name: 'watch_changes',
|
||||
description: DESCRIPTION,
|
||||
inputSchema: WatchChangesInput,
|
||||
jsonSchema: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'watch_changes',
|
||||
description: DESCRIPTION,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
enable: {
|
||||
type: 'boolean',
|
||||
description: 'true = enable the watcher; false = disable.',
|
||||
},
|
||||
const { toolDef: watchChanges, execute: executeWatchChanges } =
|
||||
makeCodecontextTool<WatchChangesInputT>({
|
||||
name: 'watch_changes',
|
||||
schema: WatchChangesInput,
|
||||
description: DESCRIPTION,
|
||||
jsonParameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
enable: {
|
||||
type: 'boolean',
|
||||
description: 'true = enable the watcher; false = disable.',
|
||||
},
|
||||
required: ['enable'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
required: ['enable'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
async execute(input, projectRoot) {
|
||||
return await executeWatchChanges(input, projectRoot);
|
||||
},
|
||||
};
|
||||
mapArgs: (input) => ({ enable: input.enable }),
|
||||
});
|
||||
|
||||
export { watchChanges, executeWatchChanges };
|
||||
|
||||
Reference in New Issue
Block a user