import { type BuiltinToolManifest } from '@lobechat/types';

import { systemPrompt } from './systemRole';
import { LocalSystemApiName, LocalSystemIdentifier } from './types';

export const LocalSystemManifest: BuiltinToolManifest = {
  executors: ['client', 'server'],
  api: [
    {
      defaultTimeoutMs: 30_000,
      description:
        'Read the content of a text or document file (txt/md/json/source code/pdf/docx/etc.). Binary files (.bin/.exe/.zip/.b64/encoded blobs) are rejected with a structured error — use runCommand with file/hexdump/strings to inspect those instead. Output is capped at 500K chars total and 8K chars per line; for larger files, use a narrower line range or grepContent.',
      humanIntervention: {
        dynamic: {
          default: 'never',
          policy: 'required',
          type: 'pathScopeAudit',
        },
      },
      name: LocalSystemApiName.readFile,
      parameters: {
        properties: {
          loc: {
            description:
              'Optional range of lines to read [startLine, endLine]. Defaults to [0, 200] if not specified.',
            items: {
              type: 'number',
            },
            type: 'array',
          },
          path: {
            description: 'The file path to read',
            type: 'string',
          },
        },
        required: ['path'],
        type: 'object',
      },
    },
    {
      defaultTimeoutMs: 60_000,
      description:
        'Search for files within the workspace based on a query string and optional filter options. Input should include the search query and any filter options. Output is a JSON array of matching file paths.',
      humanIntervention: {
        dynamic: {
          default: 'never',
          policy: 'required',
          type: 'pathScopeAudit',
        },
      },
      name: LocalSystemApiName.searchFiles,
      parameters: {
        properties: {
          contentContains: {
            description: 'The file content must contain this string',
            type: 'string',
          },
          createdAfter: {
            description:
              'Files created after this date (ISO 8601 format, e.g., 2023-10-26T10:00:00Z)',
            format: 'date-time',
            type: 'string',
          },
          createdBefore: {
            description: 'Files created before this date (ISO 8601 format)',
            format: 'date-time',
            type: 'string',
          },
          exclude: {
            description: 'Array of file or directory paths to exclude',
            items: {
              type: 'string',
            },
            type: 'array',
          },
          fileTypes: {
            description: 'Array of file types to include (e.g., "public.image", "txt")',
            items: {
              type: 'string',
            },
            type: 'array',
          },
          keywords: {
            description: 'The search keywords string (can include partial names or keywords)',
            type: 'string',
          },
          scope: {
            description:
              'Working directory scope. Limits the search to this directory. Defaults to the current working directory.',
            type: 'string',
          },
          limit: {
            description: 'Limit the number of results returned',
            type: 'number',
          },
          liveUpdate: {
            description: 'Whether to update search results live (if supported)',
            type: 'boolean',
          },
          modifiedAfter: {
            description: 'Files modified after this date (ISO 8601 format)',
            format: 'date-time',
            type: 'string',
          },
          modifiedBefore: {
            description: 'Files modified before this date (ISO 8601 format)',
            format: 'date-time',
            type: 'string',
          },
          sortBy: {
            description: 'Sort results by',
            enum: ['name', 'date', 'size'],
            type: 'string',
          },
          sortDirection: {
            description: 'Sort direction',
            enum: ['asc', 'desc'],
            type: 'string',
          },
        },
        required: ['keywords'],
        type: 'object',
      },
    },
    {
      defaultTimeoutMs: 60_000,
      description:
        'Moves or renames multiple files/directories. Input is an array of objects, each containing an oldPath and a newPath.',
      humanIntervention: {
        dynamic: {
          default: 'never',
          policy: 'required',
          type: 'pathScopeAudit',
        },
      },
      name: LocalSystemApiName.moveFiles,
      parameters: {
        properties: {
          items: {
            description: 'A list of move/rename operations to perform.',
            items: {
              properties: {
                newPath: {
                  description:
                    'The target absolute path for the file/directory (can include a new name).',
                  type: 'string',
                },
                oldPath: {
                  description: 'The current absolute path of the file/directory to move or rename.',
                  type: 'string',
                },
              },
              required: ['oldPath', 'newPath'],
              type: 'object',
            },
            type: 'array',
          },
        },
        required: ['items'],
        type: 'object',
      },
    },
    {
      defaultTimeoutMs: 30_000,
      description:
        'Write content to a specific file. Input should be the file path and content. Overwrites existing file or creates a new one.',
      humanIntervention: {
        dynamic: {
          default: 'never',
          policy: 'required',
          type: 'pathScopeAudit',
        },
      },
      name: LocalSystemApiName.writeFile,
      parameters: {
        properties: {
          content: {
            description: 'The content to write',
            type: 'string',
          },
          path: {
            description: 'The file path to write to',
            type: 'string',
          },
        },
        required: ['path', 'content'],
        type: 'object',
      },
    },
    {
      defaultTimeoutMs: 30_000,
      description:
        'Perform exact string replacements in files. Must read the file first before editing.',
      humanIntervention: {
        dynamic: {
          default: 'never',
          policy: 'required',
          type: 'pathScopeAudit',
        },
      },
      name: LocalSystemApiName.editFile,
      parameters: {
        properties: {
          file_path: {
            description: 'The absolute path to the file to modify',
            type: 'string',
          },
          new_string: {
            description: 'The text to replace with (must differ from old_string)',
            type: 'string',
          },
          old_string: {
            description: 'The exact text to replace',
            type: 'string',
          },
          replace_all: {
            description: 'Replace all occurrences of old_string (default: false)',
            type: 'boolean',
          },
        },
        required: ['file_path', 'old_string', 'new_string'],
        type: 'object',
      },
    },
    {
      defaultTimeoutMs: 30_000,
      description:
        'Start a terminal session to execute a shell command and return console output collected during the wait window (up to 30 seconds by default). If the command is still running after the wait window, the result includes `shell_id` for later observation or termination.',
      humanIntervention: 'required',
      name: LocalSystemApiName.runCommand,
      parameters: {
        properties: {
          command: {
            description: 'The shell command to execute',
            type: 'string',
          },
          description: {
            description:
              'Clear description of what this command does (5-10 words, in active voice). Use the same language as the user input.',
            type: 'string',
          },
          env: {
            additionalProperties: { type: 'string' },
            description:
              'Optional environment variables to set for this command. Use this for securely passing credentials (e.g., API tokens) — do NOT embed secrets in the command string. Values are merged into the child process environment.',
            type: 'object',
          },
          run_in_background: {
            description:
              'Set to true to return immediately after starting the terminal session. The result will include a `shell_id` for later observation or termination.',
            type: 'boolean',
          },
        },
        required: ['description', 'command'],
        type: 'object',
      },
    },
    {
      defaultTimeoutMs: 30_000,
      description:
        'Retrieve output from a running or completed background shell command. Waits for one output window (up to 30 seconds by default) and returns only new output since the last check.',
      name: LocalSystemApiName.getCommandOutput,
      parameters: {
        properties: {
          filter: {
            description:
              'Optional regex pattern to filter output lines. Only matching lines are returned.',
            type: 'string',
          },
          shell_id: {
            description: 'The ID of the background shell to retrieve output from',
            type: 'string',
          },
        },
        required: ['shell_id'],
        type: 'object',
      },
    },
    {
      defaultTimeoutMs: 10_000,
      description: 'Kill a running background shell command by its ID.',
      name: LocalSystemApiName.killCommand,
      parameters: {
        properties: {
          shell_id: {
            description: 'The ID of the background shell to kill',
            type: 'string',
          },
        },
        required: ['shell_id'],
        type: 'object',
      },
    },
    {
      defaultTimeoutMs: 60_000,
      description:
        'Search for content within files using regex patterns. Supports various output modes and filtering options.',
      humanIntervention: {
        dynamic: {
          default: 'never',
          policy: 'required',
          type: 'pathScopeAudit',
        },
      },
      name: LocalSystemApiName.grepContent,
      parameters: {
        properties: {
          '-A': {
            description:
              'Number of lines to show after each match (requires output_mode: "content")',
            type: 'number',
          },
          '-B': {
            description:
              'Number of lines to show before each match (requires output_mode: "content")',
            type: 'number',
          },
          '-C': {
            description:
              'Number of lines to show before and after each match (requires output_mode: "content")',
            type: 'number',
          },
          '-i': {
            description: 'Case insensitive search',
            type: 'boolean',
          },
          '-n': {
            description: 'Show line numbers in output (requires output_mode: "content")',
            type: 'boolean',
          },
          'glob': {
            description: 'Glob pattern to filter files (e.g. "*.js", "*.{ts,tsx}")',
            type: 'string',
          },
          'head_limit': {
            description: 'Limit output to first N results',
            type: 'number',
          },
          'multiline': {
            description: 'Enable multiline mode where . matches newlines',
            type: 'boolean',
          },
          'output_mode': {
            description:
              'Output mode: "content" (matching lines), "files_with_matches" (file paths), "count" (match counts)',
            enum: ['content', 'files_with_matches', 'count'],
            type: 'string',
          },
          'pattern': {
            description: 'The regular expression pattern to search for',
            type: 'string',
          },
          'scope': {
            description:
              'Working directory scope. Limits the search to this directory. Defaults to the current working directory.',
            type: 'string',
          },
          'type': {
            description: 'File type to search (e.g. "js", "py", "rust")',
            type: 'string',
          },
        },
        required: ['pattern'],
        type: 'object',
      },
    },
    {
      defaultTimeoutMs: 60_000,
      description:
        'Find files matching glob patterns. Supports standard glob syntax like "**/*.js" or "src/**/*.ts".',
      humanIntervention: {
        dynamic: {
          default: 'never',
          policy: 'required',
          type: 'pathScopeAudit',
        },
      },
      name: LocalSystemApiName.globFiles,
      parameters: {
        properties: {
          pattern: {
            description:
              'The glob pattern to match files against (e.g. "**/*.js", "src/**/*.ts"). Relative patterns are resolved against the scope.',
            type: 'string',
          },
          scope: {
            description:
              'Working directory scope. When `pattern` is relative, it is joined with this scope. Defaults to the current working directory.',
            type: 'string',
          },
        },
        required: ['pattern'],
        type: 'object',
      },
    },
  ],
  identifier: LocalSystemIdentifier,
  meta: {
    avatar: '📁',
    description: 'Access and manage local files, run shell commands on your desktop',
    readme:
      'Access your local filesystem on desktop. Read, write, search, and organize files. Execute shell commands with background task support and grep content with regex patterns.',
    title: 'Local System',
  },
  systemRole: systemPrompt,
  type: 'builtin',
};
