Revert Reasonix ACP wrapper local file tools

This commit is contained in:
lix-2026
2026-05-19 13:24:34 +08:00
parent ab3f06f4c4
commit 8dffd06ce1
+2 -116
View File
@@ -23,17 +23,12 @@ import { createInterface } from 'node:readline';
import { stdin, stdout } from 'node:process';
import { randomUUID } from 'node:crypto';
import { AsyncLocalStorage } from 'node:async_hooks';
import { readFileSync, existsSync, writeFileSync } from 'node:fs';
import { readFileSync, existsSync } from 'node:fs';
import { homedir } from 'node:os';
import { join, resolve } from 'node:path';
import { join } from 'node:path';
const MNOTE_WEB_URL = process.env.MNOTE_WEB_URL || 'http://127.0.0.1:3000';
const DEBUG = process.env.MNOTE_REASONIX_ACP_DEBUG === '1';
const REASONIX_ALLOWED_FS_ROOTS = (process.env.REASONIX_ALLOWED_FS_ROOTS || '')
.split(':')
.map((value) => value.trim())
.filter(Boolean)
.map((value) => resolve(value));
function debugLog(message) {
if (DEBUG) process.stderr.write(`${message}\n`);
@@ -53,64 +48,6 @@ function stableIdPart(value, fallback) {
return text || String(fallback || 'unknown');
}
function isPathWithinRoot(targetPath, rootPath) {
const normalizedRoot = rootPath.endsWith('/') ? rootPath : `${rootPath}/`;
const normalizedTarget = targetPath.endsWith('/') ? targetPath : targetPath;
return normalizedTarget === rootPath || normalizedTarget.startsWith(normalizedRoot);
}
function assertAllowedFsPath(targetPath) {
const resolved = resolve(targetPath);
if (!REASONIX_ALLOWED_FS_ROOTS.length) {
throw new Error(
'reasonix local fs tools are disabled; set REASONIX_ALLOWED_FS_ROOTS to enable them',
);
}
const matchedRoot = REASONIX_ALLOWED_FS_ROOTS.find((rootPath) => isPathWithinRoot(resolved, rootPath));
if (!matchedRoot) {
throw new Error(
`path not allowed: ${resolved}. allowed roots: ${REASONIX_ALLOWED_FS_ROOTS.join(', ')}`,
);
}
return resolved;
}
function readAllowedFsFile(targetPath) {
const resolved = assertAllowedFsPath(targetPath);
return {
path: resolved,
content: readFileSync(resolved, 'utf-8'),
};
}
function writeAllowedFsFile(targetPath, content) {
const resolved = assertAllowedFsPath(targetPath);
writeFileSync(resolved, String(content), 'utf-8');
return {
path: resolved,
written: true,
};
}
function replaceAllowedFsFile(targetPath, search, replace) {
const resolved = assertAllowedFsPath(targetPath);
const current = readFileSync(resolved, 'utf-8');
const next = String(current).split(String(search)).join(String(replace));
if (next === current) {
return {
path: resolved,
written: false,
replaced: false,
};
}
writeFileSync(resolved, next, 'utf-8');
return {
path: resolved,
written: true,
replaced: true,
};
}
function buildMnoteToolPayload(toolName, rawArgs = {}, context = {}) {
const {
actorId,
@@ -446,54 +383,6 @@ tools.register({
parallelSafe: false,
});
if (REASONIX_ALLOWED_FS_ROOTS.length) {
tools.register({
name: 'reasonix_file_read',
description: '读取允许根目录中的本地 UTF-8 文件。',
parameters: {
type: 'object',
properties: {
path: { type: 'string', description: '要读取的绝对路径文件' },
},
required: ['path'],
},
readOnly: true,
fn: async (args) => readAllowedFsFile(args.path),
parallelSafe: true,
});
tools.register({
name: 'reasonix_file_write',
description: '写入允许根目录中的本地 UTF-8 文件。',
parameters: {
type: 'object',
properties: {
path: { type: 'string', description: '要写入的绝对路径文件' },
content: { type: 'string', description: '完整文件内容' },
},
required: ['path', 'content'],
},
fn: async (args) => writeAllowedFsFile(args.path, args.content),
parallelSafe: false,
});
tools.register({
name: 'reasonix_file_replace',
description: '对允许根目录中的本地 UTF-8 文件做字符串替换。',
parameters: {
type: 'object',
properties: {
path: { type: 'string', description: '要修改的绝对路径文件' },
search: { type: 'string', description: '要查找的旧文本' },
replace: { type: 'string', description: '要替换成的新文本' },
},
required: ['path', 'search', 'replace'],
},
fn: async (args) => replaceAllowedFsFile(args.path, args.search, args.replace),
parallelSafe: false,
});
}
// ── Session Store ────────────────────────────────────
const sessions = new Map();
@@ -525,9 +414,6 @@ onRequest('session/new', async (params) => {
'Use mnote_doc_fetch to read the current document.',
'Use mnote_doc_markdown_edit to apply precise search/replace edits.',
'Always use mnote_doc_fetch first to understand the document content before editing.',
REASONIX_ALLOWED_FS_ROOTS.length
? `Local filesystem tools are enabled for these roots: ${REASONIX_ALLOWED_FS_ROOTS.join(', ')}. Use reasonix_file_read, reasonix_file_replace, or reasonix_file_write for files inside those roots.`
: 'Local filesystem tools are disabled.',
].join('\n');
const loop = new CacheFirstLoop({