Cleanup low value comments. (#248)

This commit is contained in:
Jacob Richman 2025-05-02 14:39:39 -07:00 committed by GitHub
parent 69d1c644d9
commit 0556358560
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 31 additions and 78 deletions

View File

@ -17,7 +17,7 @@ interface InputPromptProps {
setInputKey: React.Dispatch<React.SetStateAction<number>>; setInputKey: React.Dispatch<React.SetStateAction<number>>;
onSubmit: (value: string) => void; onSubmit: (value: string) => void;
showSuggestions: boolean; showSuggestions: boolean;
suggestions: Suggestion[]; // Changed to Suggestion[] suggestions: Suggestion[];
activeSuggestionIndex: number; activeSuggestionIndex: number;
navigateUp: () => void; navigateUp: () => void;
navigateDown: () => void; navigateDown: () => void;

View File

@ -48,12 +48,7 @@ export function SuggestionsDisplay({
const visibleSuggestions = suggestions.slice(startIndex, endIndex); const visibleSuggestions = suggestions.slice(startIndex, endIndex);
return ( return (
<Box <Box borderStyle="round" flexDirection="column" paddingX={1} width={width}>
borderStyle="round"
flexDirection="column"
paddingX={1}
width={width} // Use the passed width
>
{scrollOffset > 0 && <Text color="gray"></Text>} {scrollOffset > 0 && <Text color="gray"></Text>}
{visibleSuggestions.map((suggestion, index) => { {visibleSuggestions.map((suggestion, index) => {

View File

@ -66,9 +66,6 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
)} )}
</Box> </Box>
))} ))}
{/* Optional: Add padding below the last item if needed,
though ToolMessage already has some vertical space implicitly */}
{/* {tools.length > 0 && <Box height={1} />} */}
</Box> </Box>
); );
}; };

View File

@ -27,12 +27,12 @@ import {
IndividualToolCallDisplay, IndividualToolCallDisplay,
ToolCallStatus, ToolCallStatus,
} from '../types.js'; } from '../types.js';
import { isAtCommand } from '../utils/commandUtils.js'; // Import the @ command checker import { isAtCommand } from '../utils/commandUtils.js';
import { useSlashCommandProcessor } from './slashCommandProcessor.js'; import { useSlashCommandProcessor } from './slashCommandProcessor.js';
import { useShellCommandProcessor } from './shellCommandProcessor.js'; import { useShellCommandProcessor } from './shellCommandProcessor.js';
import { usePassthroughProcessor } from './passthroughCommandProcessor.js'; import { usePassthroughProcessor } from './passthroughCommandProcessor.js';
import { handleAtCommand } from './atCommandProcessor.js'; // Import the @ command handler import { handleAtCommand } from './atCommandProcessor.js';
import { findSafeSplitPoint } from '../utils/markdownUtilities.js'; // Import the split point finder import { findSafeSplitPoint } from '../utils/markdownUtilities.js';
const addHistoryItem = ( const addHistoryItem = (
setHistory: React.Dispatch<React.SetStateAction<HistoryItem[]>>, setHistory: React.Dispatch<React.SetStateAction<HistoryItem[]>>,

View File

@ -24,7 +24,6 @@ export class MarkdownRenderer {
private static _renderInline(text: string): React.ReactNode[] { private static _renderInline(text: string): React.ReactNode[] {
const nodes: React.ReactNode[] = []; const nodes: React.ReactNode[] = [];
let lastIndex = 0; let lastIndex = 0;
// UPDATED Regex: Added <u>.*?<\/u> pattern
const inlineRegex = const inlineRegex =
/(\*\*.*?\*\*|\*.*?\*|_.*?_|~~.*?~~|\[.*?\]\(.*?\)|`+.+?`+|<u>.*?<\/u>)/g; /(\*\*.*?\*\*|\*.*?\*|_.*?_|~~.*?~~|\[.*?\]\(.*?\)|`+.+?`+|<u>.*?<\/u>)/g;
let match; let match;

View File

@ -19,7 +19,7 @@ import { getFolderStructure } from '../utils/getFolderStructure.js';
import { Turn, ServerGeminiStreamEvent } from './turn.js'; import { Turn, ServerGeminiStreamEvent } from './turn.js';
import { Config } from '../config/config.js'; import { Config } from '../config/config.js';
import { getCoreSystemPrompt } from './prompts.js'; import { getCoreSystemPrompt } from './prompts.js';
import { ReadManyFilesTool } from '../tools/read-many-files.js'; // Import ReadManyFilesTool import { ReadManyFilesTool } from '../tools/read-many-files.js';
import { getResponseText } from '../utils/generateContentResponseUtilities.js'; import { getResponseText } from '../utils/generateContentResponseUtilities.js';
export class GeminiClient { export class GeminiClient {

View File

@ -12,14 +12,12 @@ import {
FunctionCall, FunctionCall,
FunctionDeclaration, FunctionDeclaration,
} from '@google/genai'; } from '@google/genai';
// Removed UI type imports
import { import {
ToolCallConfirmationDetails, ToolCallConfirmationDetails,
ToolResult, ToolResult,
ToolResultDisplay, ToolResultDisplay,
} from '../tools/tools.js'; // Keep ToolResult for now } from '../tools/tools.js';
import { getResponseText } from '../utils/generateContentResponseUtilities.js'; import { getResponseText } from '../utils/generateContentResponseUtilities.js';
// Removed gemini-stream import (types defined locally)
// --- Types for Server Logic --- // --- Types for Server Logic ---
@ -27,7 +25,7 @@ import { getResponseText } from '../utils/generateContentResponseUtilities.js';
interface ServerToolExecutionOutcome { interface ServerToolExecutionOutcome {
callId: string; callId: string;
name: string; name: string;
args: Record<string, unknown>; // Use unknown for broader compatibility args: Record<string, unknown>;
result?: ToolResult; result?: ToolResult;
error?: Error; error?: Error;
confirmationDetails: ToolCallConfirmationDetails | undefined; confirmationDetails: ToolCallConfirmationDetails | undefined;
@ -36,16 +34,14 @@ interface ServerToolExecutionOutcome {
// Define a structure for tools passed to the server // Define a structure for tools passed to the server
export interface ServerTool { export interface ServerTool {
name: string; name: string;
schema: FunctionDeclaration; // Schema is needed schema: FunctionDeclaration;
// The execute method signature might differ slightly or be wrapped // The execute method signature might differ slightly or be wrapped
execute(params: Record<string, unknown>): Promise<ToolResult>; execute(params: Record<string, unknown>): Promise<ToolResult>;
shouldConfirmExecute( shouldConfirmExecute(
params: Record<string, unknown>, params: Record<string, unknown>,
): Promise<ToolCallConfirmationDetails | false>; ): Promise<ToolCallConfirmationDetails | false>;
// validation and description might be handled differently or passed
} }
// Redefine necessary event types locally
export enum GeminiEventType { export enum GeminiEventType {
Content = 'content', Content = 'content',
ToolCallRequest = 'tool_call_request', ToolCallRequest = 'tool_call_request',
@ -80,15 +76,13 @@ export type ServerGeminiStreamEvent =
value: ServerToolCallConfirmationDetails; value: ServerToolCallConfirmationDetails;
}; };
// --- Turn Class (Refactored for Server) ---
// A turn manages the agentic loop turn within the server context. // A turn manages the agentic loop turn within the server context.
export class Turn { export class Turn {
private readonly availableTools: Map<string, ServerTool>; // Use passed-in tools private readonly availableTools: Map<string, ServerTool>;
private pendingToolCalls: Array<{ private pendingToolCalls: Array<{
callId: string; callId: string;
name: string; name: string;
args: Record<string, unknown>; // Use unknown args: Record<string, unknown>;
}>; }>;
private fnResponses: Part[]; private fnResponses: Part[];
private confirmationDetails: ToolCallConfirmationDetails[]; private confirmationDetails: ToolCallConfirmationDetails[];
@ -206,7 +200,6 @@ export class Turn {
} }
} }
// Generates a ToolCallRequest event to signal the need for execution
private handlePendingFunctionCall( private handlePendingFunctionCall(
fnCall: FunctionCall, fnCall: FunctionCall,
): ServerGeminiStreamEvent | null { ): ServerGeminiStreamEvent | null {
@ -257,12 +250,10 @@ export class Turn {
return this.confirmationDetails; return this.confirmationDetails;
} }
// Allows the service layer to get the responses needed for the next API call
getFunctionResponses(): Part[] { getFunctionResponses(): Part[] {
return this.fnResponses; return this.fnResponses;
} }
// Debugging information (optional)
getDebugResponses(): GenerateContentResponse[] { getDebugResponses(): GenerateContentResponse[] {
return this.debugResponses; return this.debugResponses;
} }

View File

@ -53,10 +53,10 @@ interface CalculatedEdit {
} }
/** /**
* Implementation of the Edit tool logic (moved from CLI) * Implementation of the Edit tool logic
*/ */
export class EditTool extends BaseTool<EditToolParams, ToolResult> { export class EditTool extends BaseTool<EditToolParams, ToolResult> {
static readonly Name = 'replace'; // Keep static name static readonly Name = 'replace';
private shouldAlwaysEdit = false; private shouldAlwaysEdit = false;
/** /**
@ -371,7 +371,7 @@ export class EditTool extends BaseTool<EditToolParams, ToolResult> {
editData.newContent, editData.newContent,
'Current', 'Current',
'Proposed', 'Proposed',
{ context: 3 }, // Removed ignoreWhitespace for potentially more accurate display diff { context: 3 },
); );
displayResult = { fileDiff }; displayResult = { fileDiff };
} }

View File

@ -27,11 +27,10 @@ export interface GlobToolParams {
} }
/** /**
* Implementation of the Glob tool logic (moved from CLI) * Implementation of the Glob tool logic
*/ */
export class GlobTool extends BaseTool<GlobToolParams, ToolResult> { export class GlobTool extends BaseTool<GlobToolParams, ToolResult> {
static readonly Name = 'glob'; // Keep static name static readonly Name = 'glob';
/** /**
* Creates a new instance of the GlobLogic * Creates a new instance of the GlobLogic
* @param rootDirectory Root directory to ground this tool in. * @param rootDirectory Root directory to ground this tool in.
@ -39,8 +38,8 @@ export class GlobTool extends BaseTool<GlobToolParams, ToolResult> {
constructor(private rootDirectory: string) { constructor(private rootDirectory: string) {
super( super(
GlobTool.Name, GlobTool.Name,
'FindFiles', // Display name handled by CLI wrapper 'FindFiles',
'Efficiently finds files matching specific glob patterns (e.g., `src/**/*.ts`, `**/*.md`), returning absolute paths sorted by modification time (newest first). Ideal for quickly locating files based on their name or path structure, especially in large codebases.', // Description handled by CLI wrapper 'Efficiently finds files matching specific glob patterns (e.g., `src/**/*.ts`, `**/*.md`), returning absolute paths sorted by modification time (newest first). Ideal for quickly locating files based on their name or path structure, especially in large codebases.',
{ {
properties: { properties: {
pattern: { pattern: {

View File

@ -5,7 +5,6 @@
*/ */
import { FunctionDeclaration, Schema } from '@google/genai'; import { FunctionDeclaration, Schema } from '@google/genai';
// Removed import for ../ui/types.js as confirmation is UI-specific
/** /**
* Interface representing the base Tool functionality * Interface representing the base Tool functionality

View File

@ -19,7 +19,7 @@ export interface WebFetchToolParams {
} }
/** /**
* Implementation of the WebFetch tool logic (moved from CLI) * Implementation of the WebFetch tool logic
*/ */
export class WebFetchTool extends BaseTool<WebFetchToolParams, ToolResult> { export class WebFetchTool extends BaseTool<WebFetchToolParams, ToolResult> {
static readonly Name: string = 'web_fetch'; static readonly Name: string = 'web_fetch';
@ -70,8 +70,6 @@ export class WebFetchTool extends BaseTool<WebFetchToolParams, ToolResult> {
return `Fetching content from ${displayUrl}`; return `Fetching content from ${displayUrl}`;
} }
// Removed shouldConfirmExecute - handled by CLI
async execute(params: WebFetchToolParams): Promise<ToolResult> { async execute(params: WebFetchToolParams): Promise<ToolResult> {
const validationError = this.validateParams(params); const validationError = this.validateParams(params);
if (validationError) { if (validationError) {
@ -86,10 +84,9 @@ export class WebFetchTool extends BaseTool<WebFetchToolParams, ToolResult> {
try { try {
const response = await fetch(url, { const response = await fetch(url, {
headers: { headers: {
// Identify the client making the request
'User-Agent': 'GeminiCode-ServerLogic/1.0', 'User-Agent': 'GeminiCode-ServerLogic/1.0',
}, },
signal: AbortSignal.timeout(15000), // Use AbortSignal for timeout signal: AbortSignal.timeout(15000),
}); });
if (!response.ok) { if (!response.ok) {

View File

@ -6,7 +6,7 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import * as Diff from 'diff'; // Keep for result generation import * as Diff from 'diff';
import { import {
BaseTool, BaseTool,
ToolResult, ToolResult,
@ -14,11 +14,10 @@ import {
ToolEditConfirmationDetails, ToolEditConfirmationDetails,
ToolConfirmationOutcome, ToolConfirmationOutcome,
ToolCallConfirmationDetails, ToolCallConfirmationDetails,
} from './tools.js'; // Updated import (Removed ToolResultDisplay) } from './tools.js';
import { SchemaValidator } from '../utils/schemaValidator.js'; // Updated import import { SchemaValidator } from '../utils/schemaValidator.js'; // Updated import
import { makeRelative, shortenPath } from '../utils/paths.js'; // Updated import import { makeRelative, shortenPath } from '../utils/paths.js'; // Updated import
import { isNodeError } from '../utils/errors.js'; // Import isNodeError import { isNodeError } from '../utils/errors.js';
/** /**
* Parameters for the WriteFile tool * Parameters for the WriteFile tool
*/ */
@ -35,7 +34,7 @@ export interface WriteFileToolParams {
} }
/** /**
* Implementation of the WriteFile tool logic (moved from CLI) * Implementation of the WriteFile tool logic
*/ */
export class WriteFileTool extends BaseTool<WriteFileToolParams, ToolResult> { export class WriteFileTool extends BaseTool<WriteFileToolParams, ToolResult> {
static readonly Name: string = 'write_file'; static readonly Name: string = 'write_file';
@ -49,7 +48,6 @@ export class WriteFileTool extends BaseTool<WriteFileToolParams, ToolResult> {
{ {
properties: { properties: {
file_path: { file_path: {
// Renamed from filePath in original schema
description: description:
"The absolute path to the file to write to (e.g., '/home/user/project/file.txt'). Relative paths are not supported.", "The absolute path to the file to write to (e.g., '/home/user/project/file.txt'). Relative paths are not supported.",
type: 'string', type: 'string',
@ -59,7 +57,7 @@ export class WriteFileTool extends BaseTool<WriteFileToolParams, ToolResult> {
type: 'string', type: 'string',
}, },
}, },
required: ['file_path', 'content'], // Use correct param names required: ['file_path', 'content'],
type: 'object', type: 'object',
}, },
); );
@ -97,15 +95,13 @@ export class WriteFileTool extends BaseTool<WriteFileToolParams, ToolResult> {
return null; return null;
} }
// Removed shouldConfirmExecute - handled by CLI
getDescription(params: WriteFileToolParams): string { getDescription(params: WriteFileToolParams): string {
const relativePath = makeRelative(params.file_path, this.rootDirectory); const relativePath = makeRelative(params.file_path, this.rootDirectory);
return `Writing to ${shortenPath(relativePath)}`; return `Writing to ${shortenPath(relativePath)}`;
} }
/** /**
* Handles the confirmation prompt for the WriteFile tool in the CLI. * Handles the confirmation prompt for the WriteFile tool.
*/ */
async shouldConfirmExecute( async shouldConfirmExecute(
params: WriteFileToolParams, params: WriteFileToolParams,
@ -203,7 +199,6 @@ export class WriteFileTool extends BaseTool<WriteFileToolParams, ToolResult> {
? `Successfully created and wrote to new file: ${params.file_path}` ? `Successfully created and wrote to new file: ${params.file_path}`
: `Successfully overwrote file: ${params.file_path}`; : `Successfully overwrote file: ${params.file_path}`;
// The returnDisplay contains the diff
const displayResult: FileDiff = { fileDiff }; const displayResult: FileDiff = { fileDiff };
return { return {
@ -218,6 +213,4 @@ export class WriteFileTool extends BaseTool<WriteFileToolParams, ToolResult> {
}; };
} }
} }
// ensureParentDirectoriesExist logic moved into execute
} }

View File

@ -12,7 +12,6 @@ import { promises as fs } from 'fs';
import { exec as _exec } from 'child_process'; import { exec as _exec } from 'child_process';
import { promisify } from 'util'; import { promisify } from 'util';
// Define the AnalysisStatus type alias
type AnalysisStatus = type AnalysisStatus =
| 'Running' | 'Running'
| 'SuccessReported' | 'SuccessReported'
@ -20,7 +19,6 @@ type AnalysisStatus =
| 'Unknown' | 'Unknown'
| 'AnalysisFailed'; | 'AnalysisFailed';
// Promisify child_process.exec for easier async/await usage
const execAsync = promisify(_exec); const execAsync = promisify(_exec);
// Identifier for the background process (e.g., PID) // Identifier for the background process (e.g., PID)
@ -33,20 +31,17 @@ export interface AnalysisResult {
inferredStatus: 'Running' | 'SuccessReported' | 'ErrorReported' | 'Unknown'; inferredStatus: 'Running' | 'SuccessReported' | 'ErrorReported' | 'Unknown';
} }
// Represents the structure returned when the LLM analysis itself fails
export interface AnalysisFailure { export interface AnalysisFailure {
error: string; error: string;
inferredStatus: 'AnalysisFailed'; inferredStatus: 'AnalysisFailed';
} }
// Type guard to check if the result is a failure object
function isAnalysisFailure( function isAnalysisFailure(
result: AnalysisResult | AnalysisFailure, result: AnalysisResult | AnalysisFailure,
): result is AnalysisFailure { ): result is AnalysisFailure {
return (result as AnalysisFailure).inferredStatus === 'AnalysisFailed'; return (result as AnalysisFailure).inferredStatus === 'AnalysisFailed';
} }
// Represents the final outcome after polling is complete (or failed/timed out)
export interface FinalAnalysisOutcome { export interface FinalAnalysisOutcome {
status: string; // e.g., 'Completed_SuccessReported', 'TimedOut_Running', 'AnalysisFailed' status: string; // e.g., 'Completed_SuccessReported', 'TimedOut_Running', 'AnalysisFailed'
summary: string; // Final summary or error message summary: string; // Final summary or error message
@ -60,7 +55,7 @@ export class BackgroundTerminalAnalyzer {
private initialDelayMs: number; private initialDelayMs: number;
constructor( constructor(
config: Config, // Accept Config object config: Config,
options: { options: {
pollIntervalMs?: number; pollIntervalMs?: number;
maxAttempts?: number; maxAttempts?: number;
@ -68,7 +63,6 @@ export class BackgroundTerminalAnalyzer {
} = {}, } = {},
) { ) {
try { try {
// Initialize Gemini client using config
this.geminiClient = new GeminiClient(config); this.geminiClient = new GeminiClient(config);
} catch (error) { } catch (error) {
console.error( console.error(
@ -262,7 +256,6 @@ export class BackgroundTerminalAnalyzer {
return { status: finalStatus, summary: finalSummary }; return { status: finalStatus, summary: finalSummary };
} }
// --- Actual Implementation of isProcessRunning ---
/** /**
* Checks if the background process is still running using OS-specific methods. * Checks if the background process is still running using OS-specific methods.
* @param pid Process handle/identifier (expects a number for standard checks). * @param pid Process handle/identifier (expects a number for standard checks).
@ -312,7 +305,6 @@ export class BackgroundTerminalAnalyzer {
} }
} }
// --- LLM Analysis Method (largely unchanged but added validation robustness) ---
private async performLlmAnalysis( private async performLlmAnalysis(
stdoutContent: string, stdoutContent: string,
stderrContent: string, stderrContent: string,
@ -433,7 +425,6 @@ Based *only* on the provided stdout and stderr:
'Unknown', 'Unknown',
]; ];
// Cast the unknown value to string before checking with includes
const statusString = resultJson?.inferredStatus as string; const statusString = resultJson?.inferredStatus as string;
const inferredStatus = validStatuses.includes( const inferredStatus = validStatuses.includes(
statusString as Exclude<AnalysisStatus, 'AnalysisFailed'>, statusString as Exclude<AnalysisStatus, 'AnalysisFailed'>,
@ -441,15 +432,13 @@ Based *only* on the provided stdout and stderr:
? (statusString as Exclude<AnalysisStatus, 'AnalysisFailed'>) ? (statusString as Exclude<AnalysisStatus, 'AnalysisFailed'>)
: 'Unknown'; : 'Unknown';
// Explicitly construct the object matching AnalysisResult type
const analysisResult: AnalysisResult = { summary, inferredStatus }; const analysisResult: AnalysisResult = { summary, inferredStatus };
return analysisResult; return analysisResult;
} catch (error: unknown) { } catch (error: unknown) {
console.error(`LLM Analysis Request Failed for PID ${pid}:`, error); console.error(`LLM Analysis Request Failed for PID ${pid}:`, error);
// Return the AnalysisFailure type
const analysisFailure: AnalysisFailure = { const analysisFailure: AnalysisFailure = {
error: `[Analysis failed: ${getErrorMessage(error)}]`, error: `[Analysis failed: ${getErrorMessage(error)}]`,
inferredStatus: 'AnalysisFailed', // This matches the AnalysisStatus type inferredStatus: 'AnalysisFailed',
}; };
return analysisFailure; return analysisFailure;
} }

View File

@ -12,12 +12,10 @@ export function getErrorMessage(error: unknown): string {
if (error instanceof Error) { if (error instanceof Error) {
return error.message; return error.message;
} else { } else {
// Attempt to convert the non-Error value to a string for logging
try { try {
const errorMessage = String(error); const errorMessage = String(error);
return errorMessage; return errorMessage;
} catch { } catch {
// If String() itself fails (highly unlikely)
return 'Failed to get error details'; return 'Failed to get error details';
} }
} }

View File

@ -66,7 +66,6 @@ async function readFullStructure(
options: MergedFolderStructureOptions, options: MergedFolderStructureOptions,
): Promise<FullFolderInfo | null> { ): Promise<FullFolderInfo | null> {
const name = path.basename(folderPath); const name = path.basename(folderPath);
// Initialize with isIgnored: false
const folderInfo: Omit<FullFolderInfo, 'totalChildren' | 'totalFiles'> = { const folderInfo: Omit<FullFolderInfo, 'totalChildren' | 'totalFiles'> = {
name, name,
path: folderPath, path: folderPath,
@ -97,7 +96,7 @@ async function readFullStructure(
subFolders: [], subFolders: [],
totalChildren: 0, // No children explored totalChildren: 0, // No children explored
totalFiles: 0, // No files explored totalFiles: 0, // No files explored
isIgnored: true, // Mark as ignored isIgnored: true,
}; };
folderInfo.subFolders.push(ignoredFolderInfo); folderInfo.subFolders.push(ignoredFolderInfo);
// Skip recursion for this folder // Skip recursion for this folder
@ -122,7 +121,6 @@ async function readFullStructure(
for (const entry of entries) { for (const entry of entries) {
if (entry.isFile()) { if (entry.isFile()) {
const fileName = entry.name; const fileName = entry.name;
// Include if no pattern or if pattern matches
if ( if (
!options.fileIncludePattern || !options.fileIncludePattern ||
options.fileIncludePattern.test(fileName) options.fileIncludePattern.test(fileName)
@ -156,7 +154,7 @@ async function readFullStructure(
} }
return { return {
...(folderInfo as FullFolderInfo), // Cast needed after conditional assignment check ...folderInfo,
totalChildren: totalChildrenCount, totalChildren: totalChildrenCount,
totalFiles: totalFileCount, totalFiles: totalFileCount,
}; };
@ -285,7 +283,6 @@ function countReducedItems(node: ReducedFolderNode): number {
/** /**
* Formats the reduced folder structure into a tree-like string. * Formats the reduced folder structure into a tree-like string.
* (No changes needed in this function)
* @param node The current node in the reduced structure. * @param node The current node in the reduced structure.
* @param indent The current indentation string. * @param indent The current indentation string.
* @param isLast Sibling indicator. * @param isLast Sibling indicator.

View File

@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import path from 'node:path'; // Import the 'path' module import path from 'node:path';
/** /**
* Shortens a path string if it exceeds maxLen, prioritizing the start and end segments. * Shortens a path string if it exceeds maxLen, prioritizing the start and end segments.

View File

@ -6,7 +6,6 @@
/** /**
* Simple utility to validate objects against JSON Schemas * Simple utility to validate objects against JSON Schemas
* In a real implementation, you would use a library like Ajv
*/ */
export class SchemaValidator { export class SchemaValidator {
/** /**