src / tools / shared.ts

/**
 * @file shared.ts
 * Shared context, types, and helpers used across all tool modules.
 */

import { resolve } from "path";
import type { PluginState } from "./stateManager";

/**
 * Mutable tool context shared by all tool modules.
 * `cwd` is updated by change_directory and visible to all tools.
 */
export interface ToolContext {
  cwd: string;
  fullState: PluginState;
  saveState: () => Promise<void>;
}

/** Validate that a path stays within the workspace boundary. */
export function validatePath(baseDir: string, requestedPath: string): string {
  const resolved = resolve(baseDir, requestedPath);
  const lowerResolved = resolved.toLowerCase();
  const lowerBase = resolve(baseDir).toLowerCase();

  if (!lowerResolved.startsWith(lowerBase)) {
    throw new Error(`Access Denied: Path '${requestedPath}' is outside the workspace.`);
  }
  return resolved;
}

/** Wrap a tool implementation with an enable/disable guard. */
export const createSafeToolImplementation = <TParameters, TReturn>(
  originalImplementation: (params: TParameters) => Promise<TReturn>,
  isEnabled: boolean,
  toolName: string,
) => async (params: TParameters): Promise<TReturn> => {
  if (!isEnabled) {
    throw new Error(
      `Tool '${toolName}' is disabled in the plugin settings. Please ask the user to enable 'Allow ${toolName.replace(/_/g, " ")}' (or similar) in the settings.`,
    );
  }
  return originalImplementation(params);
};