CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes45downloads
modifiable-tool.ts177 linesDownload Raw Back to tools
1/**2 * @license3 * Copyright 2025 Google LLC4 * SPDX-License-Identifier: Apache-2.05 */6 7import type { EditorType } from '../utils/editor.js';8import { openDiff } from '../utils/editor.js';9import os from 'node:os';10import path from 'node:path';11import fs from 'node:fs';12import { createPatchSmart } from './diffOptions.js';13import { isNodeError } from '../utils/errors.js';14import { createDebugLogger } from '../utils/debugLogger.js';15import type {16  AnyDeclarativeTool,17  DeclarativeTool,18  ToolResult,19} from './tools.js';20 21const debugLogger = createDebugLogger('MODIFIABLE_TOOL');22 23/**24 * A declarative tool that supports a modify operation.25 */26export interface ModifiableDeclarativeTool<TParams extends object>27  extends DeclarativeTool<TParams, ToolResult> {28  getModifyContext(abortSignal: AbortSignal): ModifyContext<TParams>;29}30 31export interface ModifyContext<ToolParams> {32  getFilePath: (params: ToolParams) => string;33 34  getCurrentContent: (params: ToolParams) => Promise<string>;35 36  getProposedContent: (params: ToolParams) => Promise<string>;37 38  createUpdatedParams: (39    oldContent: string,40    modifiedProposedContent: string,41    originalParams: ToolParams,42  ) => ToolParams;43}44 45export interface ModifyResult<ToolParams> {46  updatedParams: ToolParams;47  updatedDiff: string;48}49 50/**51 * Type guard to check if a declarative tool is modifiable.52 */53export function isModifiableDeclarativeTool(54  tool: AnyDeclarativeTool,55): tool is ModifiableDeclarativeTool<object> {56  return 'getModifyContext' in tool;57}58 59function createTempFilesForModify(60  currentContent: string,61  proposedContent: string,62  file_path: string,63): { oldPath: string; newPath: string } {64  const tempDir = os.tmpdir();65  const diffDir = path.join(tempDir, 'qwen-code-tool-modify-diffs');66 67  if (!fs.existsSync(diffDir)) {68    fs.mkdirSync(diffDir, { recursive: true });69  }70 71  const ext = path.extname(file_path);72  const fileName = path.basename(file_path, ext);73  const timestamp = Date.now();74  const tempOldPath = path.join(75    diffDir,76    `qwen-code-modify-${fileName}-old-${timestamp}${ext}`,77  );78  const tempNewPath = path.join(79    diffDir,80    `qwen-code-modify-${fileName}-new-${timestamp}${ext}`,81  );82 83  fs.writeFileSync(tempOldPath, currentContent, 'utf8');84  fs.writeFileSync(tempNewPath, proposedContent, 'utf8');85 86  return { oldPath: tempOldPath, newPath: tempNewPath };87}88 89function getUpdatedParams<ToolParams>(90  tmpOldPath: string,91  tempNewPath: string,92  originalParams: ToolParams,93  modifyContext: ModifyContext<ToolParams>,94): { updatedParams: ToolParams; updatedDiff: string } {95  let oldContent = '';96  let newContent = '';97 98  try {99    oldContent = fs.readFileSync(tmpOldPath, 'utf8');100  } catch (err) {101    if (!isNodeError(err) || err.code !== 'ENOENT') throw err;102    oldContent = '';103  }104 105  try {106    newContent = fs.readFileSync(tempNewPath, 'utf8');107  } catch (err) {108    if (!isNodeError(err) || err.code !== 'ENOENT') throw err;109    newContent = '';110  }111 112  const updatedParams = modifyContext.createUpdatedParams(113    oldContent,114    newContent,115    originalParams,116  );117  const updatedDiff = createPatchSmart(118    path.basename(modifyContext.getFilePath(originalParams)),119    oldContent,120    newContent,121    'Current',122    'Proposed',123  );124 125  return { updatedParams, updatedDiff };126}127 128function deleteTempFiles(oldPath: string, newPath: string): void {129  try {130    fs.unlinkSync(oldPath);131  } catch {132    debugLogger.warn(`Error deleting temp diff file: ${oldPath}`);133  }134 135  try {136    fs.unlinkSync(newPath);137  } catch {138    debugLogger.warn(`Error deleting temp diff file: ${newPath}`);139  }140}141 142/**143 * Triggers an external editor for the user to modify the proposed content,144 * and returns the updated tool parameters and the diff after the user has modified the proposed content.145 */146export async function modifyWithEditor<ToolParams>(147  originalParams: ToolParams,148  modifyContext: ModifyContext<ToolParams>,149  editorType: EditorType,150  _abortSignal: AbortSignal,151  onEditorClose: () => void,152): Promise<ModifyResult<ToolParams>> {153  const currentContent = await modifyContext.getCurrentContent(originalParams);154  const proposedContent =155    await modifyContext.getProposedContent(originalParams);156 157  const { oldPath, newPath } = createTempFilesForModify(158    currentContent,159    proposedContent,160    modifyContext.getFilePath(originalParams),161  );162 163  try {164    await openDiff(oldPath, newPath, editorType, onEditorClose);165    const result = getUpdatedParams(166      oldPath,167      newPath,168      originalParams,169      modifyContext,170    );171 172    return result;173  } finally {174    deleteTempFiles(oldPath, newPath);175  }176}177 
basant307/AI_Governance_Project · CoolFace