/**
 * Filesystem tools for the agent.
 *
 * Gives the agent read/write access to local files outside the workspace
 * (e.g. Obsidian vaults, project docs, config files).
 */
import { readFileSync, writeFileSync, mkdirSync, readdirSync, statSync, existsSync } from 'fs';
import { join, resolve, dirname } from 'path';
import { Type as T } from 'typebox';
import { wrapToolResult } from './graph-tools.js';
import { isWorkspaceOwner } from '../../services/auth-service.js';
export function createFsTools(getCurrentUser) {
    const getUser = getCurrentUser ?? (() => null);
    return [
        {
            name: 'read_file',
            description: 'Read a file from the local filesystem by absolute or ~-relative path. ' +
                'Returns the file contents as text. Use for reading docs, configs, or any file outside the workspace.',
            parameters: T.Object({
                path: T.String({ description: 'Absolute path or ~/relative path to the file' }),
            }),
            execute: async (_toolCallId, params) => {
                try {
                    const resolved = resolvePath(params.path);
                    const stat = statSync(resolved);
                    if (stat.isDirectory()) {
                        return wrapToolResult({
                            success: false,
                            error: `Path is a directory, not a file. Use list_directory instead.`,
                        });
                    }
                    const content = readFileSync(resolved, 'utf-8');
                    return wrapToolResult({ success: true, path: resolved, content });
                }
                catch (error) {
                    return wrapToolResult({
                        success: false,
                        error: error instanceof Error ? error.message : 'Unknown error',
                    });
                }
            },
        },
        {
            name: 'list_directory',
            description: 'List files and subdirectories at a given path. ' +
                'Returns names with a trailing / for directories. Use to explore folders before reading files.',
            parameters: T.Object({
                path: T.String({ description: 'Absolute path or ~/relative path to the directory' }),
            }),
            execute: async (_toolCallId, params) => {
                try {
                    const resolved = resolvePath(params.path);
                    if (!existsSync(resolved)) {
                        return wrapToolResult({ success: false, error: `Path not found: ${resolved}` });
                    }
                    const entries = readdirSync(resolved).map(name => {
                        const full = join(resolved, name);
                        try {
                            return statSync(full).isDirectory() ? `${name}/` : name;
                        }
                        catch {
                            return name;
                        }
                    });
                    return wrapToolResult({ success: true, path: resolved, entries });
                }
                catch (error) {
                    return wrapToolResult({
                        success: false,
                        error: error instanceof Error ? error.message : 'Unknown error',
                    });
                }
            },
        },
        {
            name: 'write_file',
            description: 'Write content to a file on the local filesystem (workspace owner only). Creates parent directories if needed. ' +
                'Overwrites the file if it already exists. Use for creating or updating docs, configs, or any file outside the workspace.',
            parameters: T.Object({
                path: T.String({ description: 'Absolute path or ~/relative path to the file' }),
                content: T.String({ description: 'Full file content to write' }),
            }),
            execute: async (_toolCallId, params) => {
                try {
                    const user = getUser();
                    if (user && !isWorkspaceOwner(user.role)) {
                        return wrapToolResult({ success: false, error: 'This operation requires workspace owner access.' });
                    }
                    const resolved = resolvePath(params.path);
                    mkdirSync(dirname(resolved), { recursive: true });
                    writeFileSync(resolved, params.content, 'utf-8');
                    return wrapToolResult({ success: true, path: resolved, bytesWritten: Buffer.byteLength(params.content, 'utf-8') });
                }
                catch (error) {
                    return wrapToolResult({
                        success: false,
                        error: error instanceof Error ? error.message : 'Unknown error',
                    });
                }
            },
        },
    ];
}
/** Expand ~ and resolve to absolute path */
function resolvePath(p) {
    if (p.startsWith('~/') || p === '~') {
        const home = process.env.HOME ?? process.env.USERPROFILE ?? '';
        return resolve(join(home, p.slice(1)));
    }
    return resolve(p);
}
//# sourceMappingURL=fs-tools.js.map