@gatanot/qualia_core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/background.d.ts +6 -0
- package/dist/agent/background.d.ts.map +1 -0
- package/dist/agent/background.js +58 -0
- package/dist/agent/background.js.map +1 -0
- package/dist/agent/context-builder.d.ts +23 -0
- package/dist/agent/context-builder.d.ts.map +1 -0
- package/dist/agent/context-builder.js +102 -0
- package/dist/agent/context-builder.js.map +1 -0
- package/dist/agent/diary.d.ts +4 -0
- package/dist/agent/diary.d.ts.map +1 -0
- package/dist/agent/diary.js +67 -0
- package/dist/agent/diary.js.map +1 -0
- package/dist/agent/index.d.ts +22 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +20 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/logger.d.ts +23 -0
- package/dist/agent/logger.d.ts.map +1 -0
- package/dist/agent/logger.js +70 -0
- package/dist/agent/logger.js.map +1 -0
- package/dist/agent/logger.test.d.ts +2 -0
- package/dist/agent/logger.test.d.ts.map +1 -0
- package/dist/agent/logger.test.js +28 -0
- package/dist/agent/logger.test.js.map +1 -0
- package/dist/agent/loop.d.ts +52 -0
- package/dist/agent/loop.d.ts.map +1 -0
- package/dist/agent/loop.js +557 -0
- package/dist/agent/loop.js.map +1 -0
- package/dist/agent/message-sanitizer.d.ts +13 -0
- package/dist/agent/message-sanitizer.d.ts.map +1 -0
- package/dist/agent/message-sanitizer.js +138 -0
- package/dist/agent/message-sanitizer.js.map +1 -0
- package/dist/agent/message-sanitizer.test.d.ts +2 -0
- package/dist/agent/message-sanitizer.test.d.ts.map +1 -0
- package/dist/agent/message-sanitizer.test.js +110 -0
- package/dist/agent/message-sanitizer.test.js.map +1 -0
- package/dist/agent/prompts.d.ts +15 -0
- package/dist/agent/prompts.d.ts.map +1 -0
- package/dist/agent/prompts.js +34 -0
- package/dist/agent/prompts.js.map +1 -0
- package/dist/agent/summarize-worker.d.ts +6 -0
- package/dist/agent/summarize-worker.d.ts.map +1 -0
- package/dist/agent/summarize-worker.js +62 -0
- package/dist/agent/summarize-worker.js.map +1 -0
- package/dist/agent/summarizer.d.ts +10 -0
- package/dist/agent/summarizer.d.ts.map +1 -0
- package/dist/agent/summarizer.js +133 -0
- package/dist/agent/summarizer.js.map +1 -0
- package/dist/agent/types.d.ts +135 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +21 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/ai/base.d.ts +19 -0
- package/dist/ai/base.d.ts.map +1 -0
- package/dist/ai/base.js +2 -0
- package/dist/ai/base.js.map +1 -0
- package/dist/ai/deepseek.d.ts +15 -0
- package/dist/ai/deepseek.d.ts.map +1 -0
- package/dist/ai/deepseek.js +24 -0
- package/dist/ai/deepseek.js.map +1 -0
- package/dist/ai/factory.d.ts +4 -0
- package/dist/ai/factory.d.ts.map +1 -0
- package/dist/ai/factory.js +53 -0
- package/dist/ai/factory.js.map +1 -0
- package/dist/ai/index.d.ts +43 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +36 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/models.d.ts +13 -0
- package/dist/ai/models.d.ts.map +1 -0
- package/dist/ai/models.js +67 -0
- package/dist/ai/models.js.map +1 -0
- package/dist/ai/ollama.d.ts +13 -0
- package/dist/ai/ollama.d.ts.map +1 -0
- package/dist/ai/ollama.js +32 -0
- package/dist/ai/ollama.js.map +1 -0
- package/dist/ai/openai.d.ts +46 -0
- package/dist/ai/openai.d.ts.map +1 -0
- package/dist/ai/openai.js +90 -0
- package/dist/ai/openai.js.map +1 -0
- package/dist/ai/types.d.ts +154 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +2 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/ai/utils.d.ts +47 -0
- package/dist/ai/utils.d.ts.map +1 -0
- package/dist/ai/utils.js +145 -0
- package/dist/ai/utils.js.map +1 -0
- package/dist/ai/xiaomi.d.ts +15 -0
- package/dist/ai/xiaomi.d.ts.map +1 -0
- package/dist/ai/xiaomi.js +23 -0
- package/dist/ai/xiaomi.js.map +1 -0
- package/dist/chat-confirm.d.ts +4 -0
- package/dist/chat-confirm.d.ts.map +1 -0
- package/dist/chat-confirm.js +2 -0
- package/dist/chat-confirm.js.map +1 -0
- package/dist/chat-steering.d.ts +6 -0
- package/dist/chat-steering.d.ts.map +1 -0
- package/dist/chat-steering.js +2 -0
- package/dist/chat-steering.js.map +1 -0
- package/dist/concurrency/background-worker.d.ts +16 -0
- package/dist/concurrency/background-worker.d.ts.map +1 -0
- package/dist/concurrency/background-worker.js +62 -0
- package/dist/concurrency/background-worker.js.map +1 -0
- package/dist/concurrency/background-worker.test.d.ts +2 -0
- package/dist/concurrency/background-worker.test.d.ts.map +1 -0
- package/dist/concurrency/background-worker.test.js +55 -0
- package/dist/concurrency/background-worker.test.js.map +1 -0
- package/dist/concurrency/file-mutex.d.ts +8 -0
- package/dist/concurrency/file-mutex.d.ts.map +1 -0
- package/dist/concurrency/file-mutex.js +41 -0
- package/dist/concurrency/file-mutex.js.map +1 -0
- package/dist/concurrency/file-mutex.test.d.ts +2 -0
- package/dist/concurrency/file-mutex.test.d.ts.map +1 -0
- package/dist/concurrency/file-mutex.test.js +50 -0
- package/dist/concurrency/file-mutex.test.js.map +1 -0
- package/dist/concurrency/index.d.ts +5 -0
- package/dist/concurrency/index.d.ts.map +1 -0
- package/dist/concurrency/index.js +4 -0
- package/dist/concurrency/index.js.map +1 -0
- package/dist/concurrency/session-lock.d.ts +8 -0
- package/dist/concurrency/session-lock.d.ts.map +1 -0
- package/dist/concurrency/session-lock.js +41 -0
- package/dist/concurrency/session-lock.js.map +1 -0
- package/dist/concurrency/session-lock.test.d.ts +2 -0
- package/dist/concurrency/session-lock.test.d.ts.map +1 -0
- package/dist/concurrency/session-lock.test.js +51 -0
- package/dist/concurrency/session-lock.test.js.map +1 -0
- package/dist/config/index.d.ts +12 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +10 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/store.d.ts +17 -0
- package/dist/config/store.d.ts.map +1 -0
- package/dist/config/store.js +214 -0
- package/dist/config/store.js.map +1 -0
- package/dist/config/types.d.ts +44 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/gateway/adapters/email.d.ts +23 -0
- package/dist/gateway/adapters/email.d.ts.map +1 -0
- package/dist/gateway/adapters/email.js +145 -0
- package/dist/gateway/adapters/email.js.map +1 -0
- package/dist/gateway/adapters/telegram-sessions.d.ts +4 -0
- package/dist/gateway/adapters/telegram-sessions.d.ts.map +1 -0
- package/dist/gateway/adapters/telegram-sessions.js +39 -0
- package/dist/gateway/adapters/telegram-sessions.js.map +1 -0
- package/dist/gateway/adapters/telegram.d.ts +22 -0
- package/dist/gateway/adapters/telegram.d.ts.map +1 -0
- package/dist/gateway/adapters/telegram.js +131 -0
- package/dist/gateway/adapters/telegram.js.map +1 -0
- package/dist/gateway/dispatcher.d.ts +19 -0
- package/dist/gateway/dispatcher.d.ts.map +1 -0
- package/dist/gateway/dispatcher.js +81 -0
- package/dist/gateway/dispatcher.js.map +1 -0
- package/dist/gateway/inbound-handler.d.ts +3 -0
- package/dist/gateway/inbound-handler.d.ts.map +1 -0
- package/dist/gateway/inbound-handler.js +95 -0
- package/dist/gateway/inbound-handler.js.map +1 -0
- package/dist/gateway/index.d.ts +9 -0
- package/dist/gateway/index.d.ts.map +1 -0
- package/dist/gateway/index.js +6 -0
- package/dist/gateway/index.js.map +1 -0
- package/dist/gateway/lifecycle.d.ts +3 -0
- package/dist/gateway/lifecycle.d.ts.map +1 -0
- package/dist/gateway/lifecycle.js +38 -0
- package/dist/gateway/lifecycle.js.map +1 -0
- package/dist/gateway/types.d.ts +32 -0
- package/dist/gateway/types.d.ts.map +1 -0
- package/dist/gateway/types.js +2 -0
- package/dist/gateway/types.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown.d.ts +2 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +94 -0
- package/dist/markdown.js.map +1 -0
- package/dist/paths.d.ts +5 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +17 -0
- package/dist/paths.js.map +1 -0
- package/dist/storage/index.d.ts +10 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +18 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/memory.d.ts +39 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +252 -0
- package/dist/storage/memory.js.map +1 -0
- package/dist/storage/sqlite.d.ts +44 -0
- package/dist/storage/sqlite.d.ts.map +1 -0
- package/dist/storage/sqlite.js +275 -0
- package/dist/storage/sqlite.js.map +1 -0
- package/dist/storage/types.d.ts +134 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/storage/utils.d.ts +2 -0
- package/dist/storage/utils.d.ts.map +1 -0
- package/dist/storage/utils.js +8 -0
- package/dist/storage/utils.js.map +1 -0
- package/dist/task/executor.d.ts +3 -0
- package/dist/task/executor.d.ts.map +1 -0
- package/dist/task/executor.js +80 -0
- package/dist/task/executor.js.map +1 -0
- package/dist/task/index.d.ts +5 -0
- package/dist/task/index.d.ts.map +1 -0
- package/dist/task/index.js +4 -0
- package/dist/task/index.js.map +1 -0
- package/dist/task/scheduler.d.ts +5 -0
- package/dist/task/scheduler.d.ts.map +1 -0
- package/dist/task/scheduler.js +47 -0
- package/dist/task/scheduler.js.map +1 -0
- package/dist/task/store.d.ts +14 -0
- package/dist/task/store.d.ts.map +1 -0
- package/dist/task/store.js +156 -0
- package/dist/task/store.js.map +1 -0
- package/dist/task/types.d.ts +13 -0
- package/dist/task/types.d.ts.map +1 -0
- package/dist/task/types.js +2 -0
- package/dist/task/types.js.map +1 -0
- package/dist/tool/env.d.ts +20 -0
- package/dist/tool/env.d.ts.map +1 -0
- package/dist/tool/env.js +26 -0
- package/dist/tool/env.js.map +1 -0
- package/dist/tool/env.test.d.ts +2 -0
- package/dist/tool/env.test.d.ts.map +1 -0
- package/dist/tool/env.test.js +42 -0
- package/dist/tool/env.test.js.map +1 -0
- package/dist/tool/index.d.ts +42 -0
- package/dist/tool/index.d.ts.map +1 -0
- package/dist/tool/index.js +53 -0
- package/dist/tool/index.js.map +1 -0
- package/dist/tool/registry.d.ts +43 -0
- package/dist/tool/registry.d.ts.map +1 -0
- package/dist/tool/registry.js +79 -0
- package/dist/tool/registry.js.map +1 -0
- package/dist/tool/safeguard.d.ts +21 -0
- package/dist/tool/safeguard.d.ts.map +1 -0
- package/dist/tool/safeguard.js +212 -0
- package/dist/tool/safeguard.js.map +1 -0
- package/dist/tool/tools/delete-file.d.ts +10 -0
- package/dist/tool/tools/delete-file.d.ts.map +1 -0
- package/dist/tool/tools/delete-file.js +52 -0
- package/dist/tool/tools/delete-file.js.map +1 -0
- package/dist/tool/tools/edit.d.ts +10 -0
- package/dist/tool/tools/edit.d.ts.map +1 -0
- package/dist/tool/tools/edit.js +159 -0
- package/dist/tool/tools/edit.js.map +1 -0
- package/dist/tool/tools/exec.d.ts +12 -0
- package/dist/tool/tools/exec.d.ts.map +1 -0
- package/dist/tool/tools/exec.js +170 -0
- package/dist/tool/tools/exec.js.map +1 -0
- package/dist/tool/tools/file-utils.d.ts +13 -0
- package/dist/tool/tools/file-utils.d.ts.map +1 -0
- package/dist/tool/tools/file-utils.js +65 -0
- package/dist/tool/tools/file-utils.js.map +1 -0
- package/dist/tool/tools/read-file.d.ts +10 -0
- package/dist/tool/tools/read-file.d.ts.map +1 -0
- package/dist/tool/tools/read-file.js +116 -0
- package/dist/tool/tools/read-file.js.map +1 -0
- package/dist/tool/tools/read-memory.d.ts +3 -0
- package/dist/tool/tools/read-memory.d.ts.map +1 -0
- package/dist/tool/tools/read-memory.js +58 -0
- package/dist/tool/tools/read-memory.js.map +1 -0
- package/dist/tool/tools/read-tasks.d.ts +3 -0
- package/dist/tool/tools/read-tasks.d.ts.map +1 -0
- package/dist/tool/tools/read-tasks.js +29 -0
- package/dist/tool/tools/read-tasks.js.map +1 -0
- package/dist/tool/tools/schedule-task.d.ts +3 -0
- package/dist/tool/tools/schedule-task.d.ts.map +1 -0
- package/dist/tool/tools/schedule-task.js +50 -0
- package/dist/tool/tools/schedule-task.js.map +1 -0
- package/dist/tool/tools/search-history.d.ts +4 -0
- package/dist/tool/tools/search-history.d.ts.map +1 -0
- package/dist/tool/tools/search-history.js +58 -0
- package/dist/tool/tools/search-history.js.map +1 -0
- package/dist/tool/tools/web-search.d.ts +3 -0
- package/dist/tool/tools/web-search.d.ts.map +1 -0
- package/dist/tool/tools/web-search.js +89 -0
- package/dist/tool/tools/web-search.js.map +1 -0
- package/dist/tool/tools/write-file.d.ts +11 -0
- package/dist/tool/tools/write-file.d.ts.map +1 -0
- package/dist/tool/tools/write-file.js +79 -0
- package/dist/tool/tools/write-file.js.map +1 -0
- package/dist/tool/tools/write-memory.d.ts +3 -0
- package/dist/tool/tools/write-memory.d.ts.map +1 -0
- package/dist/tool/tools/write-memory.js +99 -0
- package/dist/tool/tools/write-memory.js.map +1 -0
- package/dist/tool/types.d.ts +63 -0
- package/dist/tool/types.d.ts.map +1 -0
- package/dist/tool/types.js +33 -0
- package/dist/tool/types.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { PendingConfirmation } from '../types.js';
|
|
3
|
+
import { stripBom, detectMeta, normalizeToLF, atomicWrite } from './file-utils.js';
|
|
4
|
+
function escapeNewlines(s) {
|
|
5
|
+
return s.replace(/\r/g, '\\r').replace(/\n/g, '\\n');
|
|
6
|
+
}
|
|
7
|
+
function formatDiff(original, replacement) {
|
|
8
|
+
return `- ${escapeNewlines(original)}\n+ ${escapeNewlines(replacement)}`;
|
|
9
|
+
}
|
|
10
|
+
function countOccurrences(haystack, needle) {
|
|
11
|
+
if (!needle)
|
|
12
|
+
return 0;
|
|
13
|
+
let count = 0;
|
|
14
|
+
let pos = 0;
|
|
15
|
+
while (true) {
|
|
16
|
+
pos = haystack.indexOf(needle, pos);
|
|
17
|
+
if (pos === -1)
|
|
18
|
+
break;
|
|
19
|
+
count++;
|
|
20
|
+
pos += needle.length;
|
|
21
|
+
}
|
|
22
|
+
return count;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* edit — 精确字符串替换编辑文件
|
|
26
|
+
*
|
|
27
|
+
* 在文件中查找 oldString 并替换为 newString。
|
|
28
|
+
* 使用原子写入,自动保留原文件的 BOM 和行尾格式。
|
|
29
|
+
* 非 replaceAll 模式下,oldString 必须在文件中恰好出现一次。
|
|
30
|
+
*/
|
|
31
|
+
export const editTool = {
|
|
32
|
+
name: 'edit',
|
|
33
|
+
description: 'Perform exact string replacement in a file. Find oldString and replace with newString. In non-replaceAll mode, oldString must appear exactly once (prevents accidental changes). Preserves BOM and line endings (CRLF/LF).',
|
|
34
|
+
parameters: {
|
|
35
|
+
type: 'object',
|
|
36
|
+
properties: {
|
|
37
|
+
path: {
|
|
38
|
+
type: 'string',
|
|
39
|
+
description: 'File path (relative to workspace or absolute)'
|
|
40
|
+
},
|
|
41
|
+
oldString: {
|
|
42
|
+
type: 'string',
|
|
43
|
+
description: 'Original text to replace (must match file content exactly, including indentation and blank lines)'
|
|
44
|
+
},
|
|
45
|
+
newString: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
description: 'Replacement text'
|
|
48
|
+
},
|
|
49
|
+
replaceAll: {
|
|
50
|
+
type: 'boolean',
|
|
51
|
+
description: 'Replace all occurrences. Default false — oldString must appear exactly once in the file.'
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
required: ['path', 'oldString', 'newString']
|
|
55
|
+
},
|
|
56
|
+
async execute(args, ctx) {
|
|
57
|
+
const userPath = args.path;
|
|
58
|
+
const oldString = args.oldString;
|
|
59
|
+
const newString = args.newString;
|
|
60
|
+
const replaceAll = args.replaceAll === true;
|
|
61
|
+
if (!userPath) {
|
|
62
|
+
return { success: false, output: '', error: '缺少参数: path' };
|
|
63
|
+
}
|
|
64
|
+
if (oldString === undefined || oldString === null) {
|
|
65
|
+
return { success: false, output: '', error: '缺少参数: oldString' };
|
|
66
|
+
}
|
|
67
|
+
if (newString === undefined || newString === null) {
|
|
68
|
+
return { success: false, output: '', error: '缺少参数: newString' };
|
|
69
|
+
}
|
|
70
|
+
if (oldString === '') {
|
|
71
|
+
return { success: false, output: '', error: 'oldString 不能为空' };
|
|
72
|
+
}
|
|
73
|
+
if (oldString === newString) {
|
|
74
|
+
return { success: false, output: '', error: 'oldString 与 newString 相同,无需替换' };
|
|
75
|
+
}
|
|
76
|
+
const resolved = ctx.resolvePath(userPath);
|
|
77
|
+
const { path: filePath, classification } = resolved;
|
|
78
|
+
if (!args.__confirmed) {
|
|
79
|
+
if (classification === 'reject') {
|
|
80
|
+
return { success: false, output: '', error: `拒绝编辑系统路径: ${userPath}` };
|
|
81
|
+
}
|
|
82
|
+
if (classification === 'confirm') {
|
|
83
|
+
throw new PendingConfirmation('edit', { path: userPath, oldString, newString, replaceAll }, `文件 "${userPath}" 在工作区之外,确认编辑?`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const raw = await readFile(filePath, 'utf-8');
|
|
88
|
+
const meta = detectMeta(raw);
|
|
89
|
+
const content = stripBom(raw);
|
|
90
|
+
// Strategy 1: exact match on original content
|
|
91
|
+
let matchCount = countOccurrences(content, oldString);
|
|
92
|
+
let effectiveOld = oldString;
|
|
93
|
+
// Strategy 2: line-ending normalized match
|
|
94
|
+
if (matchCount === 0) {
|
|
95
|
+
const lfContent = normalizeToLF(content);
|
|
96
|
+
const lfOld = normalizeToLF(oldString);
|
|
97
|
+
const lfCount = countOccurrences(lfContent, lfOld);
|
|
98
|
+
if (lfCount > 0) {
|
|
99
|
+
matchCount = lfCount;
|
|
100
|
+
effectiveOld = lfOld;
|
|
101
|
+
// Apply replacement on LF-normalized content, then restore line endings
|
|
102
|
+
const lfNew = normalizeToLF(newString);
|
|
103
|
+
let result;
|
|
104
|
+
if (replaceAll) {
|
|
105
|
+
result = lfContent.split(lfOld).join(lfNew);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
result = lfContent.replace(lfOld, lfNew);
|
|
109
|
+
}
|
|
110
|
+
// Re-apply original content's line endings
|
|
111
|
+
if (meta.lineEnding === 'CRLF') {
|
|
112
|
+
result = result.replace(/\n/g, '\r\n');
|
|
113
|
+
}
|
|
114
|
+
await atomicWrite(filePath, result, meta);
|
|
115
|
+
const actualCount = replaceAll ? matchCount : 1;
|
|
116
|
+
return {
|
|
117
|
+
success: true,
|
|
118
|
+
output: `已编辑: ${userPath}\n替换 ${actualCount} 处:\n${formatDiff(oldString, newString)}`
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (matchCount === 0) {
|
|
123
|
+
return {
|
|
124
|
+
success: false,
|
|
125
|
+
output: '',
|
|
126
|
+
error: `未在文件中找到 oldString。请确保 oldString 与文件内容完全一致(包括缩进和空行)。\n` +
|
|
127
|
+
`文件路径: ${userPath}\n` +
|
|
128
|
+
`oldString: ${escapeNewlines(oldString.slice(0, 200))}`
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
if (!replaceAll && matchCount > 1) {
|
|
132
|
+
return {
|
|
133
|
+
success: false,
|
|
134
|
+
output: '',
|
|
135
|
+
error: `oldString 在文件中出现了 ${matchCount} 次。请提供更多上下文使匹配唯一,或设置 replaceAll: true 替换全部。`
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// Strategy 1: exact match, apply directly
|
|
139
|
+
const result = replaceAll
|
|
140
|
+
? content.split(oldString).join(newString)
|
|
141
|
+
: content.replace(oldString, newString);
|
|
142
|
+
await atomicWrite(filePath, result, meta);
|
|
143
|
+
const actualCount = replaceAll ? matchCount : 1;
|
|
144
|
+
return {
|
|
145
|
+
success: true,
|
|
146
|
+
output: `已编辑: ${userPath}\n替换 ${actualCount} 处:\n${formatDiff(oldString, newString)}`
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
if (error.code === 'ENOENT') {
|
|
151
|
+
return { success: false, output: '', error: `文件不存在: ${userPath}` };
|
|
152
|
+
}
|
|
153
|
+
if (error instanceof PendingConfirmation)
|
|
154
|
+
throw error;
|
|
155
|
+
return { success: false, output: '', error: `编辑失败: ${error.message}` };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
//# sourceMappingURL=edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/tool/tools/edit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ToolDef } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* execute_command — 执行终端命令
|
|
4
|
+
*
|
|
5
|
+
* 安全策略:
|
|
6
|
+
* - 安全命令 + 工作区路径 → 直接执行
|
|
7
|
+
* - 危险命令 → 需用户确认
|
|
8
|
+
* - format/diskpart → 拒绝
|
|
9
|
+
* - 默认超时 5 分钟,输出上限 50KB
|
|
10
|
+
*/
|
|
11
|
+
export declare const execTool: ToolDef;
|
|
12
|
+
//# sourceMappingURL=exec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../../src/tool/tools/exec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AA4BvD;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,EAAE,OA8ItB,CAAC"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { spawn, execSync } from 'node:child_process';
|
|
2
|
+
import { PendingConfirmation } from '../types.js';
|
|
3
|
+
const DEFAULT_TIMEOUT = 300_000;
|
|
4
|
+
const MAX_ALLOWED_TIMEOUT = 3_600_000;
|
|
5
|
+
const MAX_OUTPUT = 50_000;
|
|
6
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
7
|
+
function killProcessTree(pid) {
|
|
8
|
+
if (pid == null)
|
|
9
|
+
return false;
|
|
10
|
+
if (IS_WINDOWS) {
|
|
11
|
+
try {
|
|
12
|
+
execSync(`taskkill /F /T /PID ${pid}`, { stdio: 'ignore' });
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
process.kill(pid, 'SIGKILL');
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* execute_command — 执行终端命令
|
|
29
|
+
*
|
|
30
|
+
* 安全策略:
|
|
31
|
+
* - 安全命令 + 工作区路径 → 直接执行
|
|
32
|
+
* - 危险命令 → 需用户确认
|
|
33
|
+
* - format/diskpart → 拒绝
|
|
34
|
+
* - 默认超时 5 分钟,输出上限 50KB
|
|
35
|
+
*/
|
|
36
|
+
export const execTool = {
|
|
37
|
+
name: 'execute_command',
|
|
38
|
+
description: 'Execute a terminal command in the workspace directory and return output. For development tasks only, non-interactive. Default timeout 5 minutes.',
|
|
39
|
+
parameters: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: {
|
|
42
|
+
command: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
description: 'The terminal command to execute'
|
|
45
|
+
},
|
|
46
|
+
timeout: {
|
|
47
|
+
type: 'number',
|
|
48
|
+
description: 'Timeout in seconds, default 300 (5 min), max 3600 (1 hour)'
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
required: ['command']
|
|
52
|
+
},
|
|
53
|
+
async execute(args, ctx) {
|
|
54
|
+
const command = args.command;
|
|
55
|
+
if (!command) {
|
|
56
|
+
return { success: false, output: '', error: '缺少参数: command' };
|
|
57
|
+
}
|
|
58
|
+
let timeoutSec = typeof args.timeout === 'number' && args.timeout > 0 ? args.timeout : DEFAULT_TIMEOUT / 1000;
|
|
59
|
+
if (timeoutSec > MAX_ALLOWED_TIMEOUT / 1000)
|
|
60
|
+
timeoutSec = MAX_ALLOWED_TIMEOUT / 1000;
|
|
61
|
+
const timeoutMs = timeoutSec * 1000;
|
|
62
|
+
const classification = ctx.classifyCommand(command);
|
|
63
|
+
if (classification === 'reject') {
|
|
64
|
+
return {
|
|
65
|
+
success: false,
|
|
66
|
+
output: '',
|
|
67
|
+
error: `拒绝执行危险命令: ${command.slice(0, 80)}`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (classification === 'confirm' && !args.__confirmed) {
|
|
71
|
+
throw new PendingConfirmation('execute_command', { ...args }, `需要确认执行命令:\n${command}`);
|
|
72
|
+
}
|
|
73
|
+
if (args.__confirmed) {
|
|
74
|
+
const recheck = ctx.classifyCommand(command);
|
|
75
|
+
if (recheck === 'reject') {
|
|
76
|
+
return {
|
|
77
|
+
success: false,
|
|
78
|
+
output: '',
|
|
79
|
+
error: `拒绝执行危险命令: ${command.slice(0, 80)}`
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return new Promise((resolve) => {
|
|
84
|
+
const stdoutChunks = [];
|
|
85
|
+
const stderrChunks = [];
|
|
86
|
+
let resolved = false;
|
|
87
|
+
let totalOutput = 0;
|
|
88
|
+
const resolveResult = (success, error) => {
|
|
89
|
+
if (resolved)
|
|
90
|
+
return;
|
|
91
|
+
resolved = true;
|
|
92
|
+
clearTimeout(timer);
|
|
93
|
+
const out = Buffer.concat(stdoutChunks).toString();
|
|
94
|
+
const err = Buffer.concat(stderrChunks).toString();
|
|
95
|
+
const output = [out, err ? `\n[stderr]\n${err}` : '']
|
|
96
|
+
.filter(Boolean)
|
|
97
|
+
.join('')
|
|
98
|
+
.slice(0, MAX_OUTPUT);
|
|
99
|
+
resolve({
|
|
100
|
+
success,
|
|
101
|
+
output: output || '(无输出)',
|
|
102
|
+
error
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
const timer = setTimeout(() => {
|
|
106
|
+
if (!resolved) {
|
|
107
|
+
if (!killProcessTree(child.pid)) {
|
|
108
|
+
try {
|
|
109
|
+
child.kill();
|
|
110
|
+
}
|
|
111
|
+
catch { /* 忽略二次杀死失败 */ }
|
|
112
|
+
}
|
|
113
|
+
resolveResult(false, `命令执行超时 (${timeoutSec} 秒)`);
|
|
114
|
+
}
|
|
115
|
+
}, timeoutMs);
|
|
116
|
+
const child = spawn(command, [], {
|
|
117
|
+
cwd: ctx.root,
|
|
118
|
+
shell: IS_WINDOWS ? 'powershell.exe' : '/bin/bash',
|
|
119
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
120
|
+
});
|
|
121
|
+
child.stdout?.on('data', (data) => {
|
|
122
|
+
stdoutChunks.push(data);
|
|
123
|
+
totalOutput += data.length;
|
|
124
|
+
if (totalOutput > MAX_OUTPUT) {
|
|
125
|
+
if (!resolved) {
|
|
126
|
+
if (!killProcessTree(child.pid)) {
|
|
127
|
+
try {
|
|
128
|
+
child.kill();
|
|
129
|
+
}
|
|
130
|
+
catch { /* ignore */ }
|
|
131
|
+
}
|
|
132
|
+
resolveResult(false, '命令输出超过上限 (50KB)');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
ctx.onUpdate?.(data.toString());
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
child.stderr?.on('data', (data) => {
|
|
140
|
+
stderrChunks.push(data);
|
|
141
|
+
totalOutput += data.length;
|
|
142
|
+
if (totalOutput > MAX_OUTPUT) {
|
|
143
|
+
if (!resolved) {
|
|
144
|
+
if (!killProcessTree(child.pid)) {
|
|
145
|
+
try {
|
|
146
|
+
child.kill();
|
|
147
|
+
}
|
|
148
|
+
catch { /* ignore */ }
|
|
149
|
+
}
|
|
150
|
+
resolveResult(false, '命令输出超过上限 (50KB)');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
ctx.onUpdate?.(data.toString());
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
child.on('close', (code) => {
|
|
158
|
+
if (resolved)
|
|
159
|
+
return;
|
|
160
|
+
resolveResult(code === 0, code !== 0 ? `命令退出码: ${code}` : undefined);
|
|
161
|
+
});
|
|
162
|
+
child.on('error', (err) => {
|
|
163
|
+
if (resolved)
|
|
164
|
+
return;
|
|
165
|
+
resolveResult(false, err.message);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=exec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../src/tool/tools/exec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type LineEnding = 'LF' | 'CRLF';
|
|
2
|
+
export interface FileMeta {
|
|
3
|
+
bom: boolean;
|
|
4
|
+
lineEnding: LineEnding;
|
|
5
|
+
}
|
|
6
|
+
export declare function stripBom(content: string): string;
|
|
7
|
+
export declare function detectLineEnding(content: string): LineEnding;
|
|
8
|
+
export declare function detectMeta(content: string): FileMeta;
|
|
9
|
+
export declare function normalizeLineEndings(content: string, target: LineEnding): string;
|
|
10
|
+
export declare function normalizeToLF(content: string): string;
|
|
11
|
+
export declare function applyMeta(content: string, meta: FileMeta): string;
|
|
12
|
+
export declare function atomicWrite(filePath: string, content: string, meta?: FileMeta): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=file-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../../src/tool/tools/file-utils.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,MAAM,CAAC;AAEvC,MAAM,WAAW,QAAQ;IACxB,GAAG,EAAE,OAAO,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;CACvB;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKhD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAK5D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAKpD;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAKhF;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAQjE;AAED,wBAAsB,WAAW,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,QAAQ,GACb,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { writeFile, rename, stat, chmod } from 'node:fs/promises';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
const BOM = '\uFEFF';
|
|
5
|
+
export function stripBom(content) {
|
|
6
|
+
if (content.startsWith(BOM)) {
|
|
7
|
+
return content.slice(1);
|
|
8
|
+
}
|
|
9
|
+
return content;
|
|
10
|
+
}
|
|
11
|
+
export function detectLineEnding(content) {
|
|
12
|
+
if (content.includes('\r\n')) {
|
|
13
|
+
return 'CRLF';
|
|
14
|
+
}
|
|
15
|
+
return 'LF';
|
|
16
|
+
}
|
|
17
|
+
export function detectMeta(content) {
|
|
18
|
+
return {
|
|
19
|
+
bom: content.startsWith(BOM),
|
|
20
|
+
lineEnding: detectLineEnding(content)
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export function normalizeLineEndings(content, target) {
|
|
24
|
+
if (target === 'CRLF') {
|
|
25
|
+
return content.replace(/\r\n/g, '\n').replace(/\n/g, '\r\n');
|
|
26
|
+
}
|
|
27
|
+
return content.replace(/\r\n/g, '\n');
|
|
28
|
+
}
|
|
29
|
+
export function normalizeToLF(content) {
|
|
30
|
+
return content.replace(/\r\n/g, '\n');
|
|
31
|
+
}
|
|
32
|
+
export function applyMeta(content, meta) {
|
|
33
|
+
let result = normalizeLineEndings(content, meta.lineEnding);
|
|
34
|
+
if (meta.bom && !result.startsWith(BOM)) {
|
|
35
|
+
result = BOM + result;
|
|
36
|
+
}
|
|
37
|
+
else if (!meta.bom && result.startsWith(BOM)) {
|
|
38
|
+
result = result.slice(1);
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
export async function atomicWrite(filePath, content, meta) {
|
|
43
|
+
let finalContent = content;
|
|
44
|
+
let targetMode = null;
|
|
45
|
+
try {
|
|
46
|
+
const info = await stat(filePath);
|
|
47
|
+
if (info.isFile()) {
|
|
48
|
+
targetMode = info.mode;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// new file, no mode to preserve
|
|
53
|
+
}
|
|
54
|
+
if (meta) {
|
|
55
|
+
finalContent = applyMeta(content, meta);
|
|
56
|
+
}
|
|
57
|
+
const dir = dirname(filePath);
|
|
58
|
+
const tmpPath = filePath + '.' + randomUUID() + '.tmp';
|
|
59
|
+
await writeFile(tmpPath, finalContent, 'utf-8');
|
|
60
|
+
if (targetMode !== null) {
|
|
61
|
+
await chmod(tmpPath, targetMode);
|
|
62
|
+
}
|
|
63
|
+
await rename(tmpPath, filePath);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=file-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../../src/tool/tools/file-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ToolDef } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* read_file — 读取文件内容
|
|
4
|
+
*
|
|
5
|
+
* 工作区内文件直接读取;工作区外文件需用户确认。
|
|
6
|
+
* 文件大小限制 1 MB,超限返回错误。
|
|
7
|
+
* 支持 offset / limit 按行翻页,不指定时默认读前 500 行。
|
|
8
|
+
*/
|
|
9
|
+
export declare const readFileTool: ToolDef;
|
|
10
|
+
//# sourceMappingURL=read-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-file.d.ts","sourceRoot":"","sources":["../../../src/tool/tools/read-file.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAiBvD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,OA2G1B,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { PendingConfirmation } from '../types.js';
|
|
3
|
+
import { stripBom } from './file-utils.js';
|
|
4
|
+
const MAX_FILE_SIZE = 1024 * 1024;
|
|
5
|
+
const DEFAULT_OFFSET = 1;
|
|
6
|
+
const DEFAULT_LIMIT = 500;
|
|
7
|
+
function validateParam(name, value) {
|
|
8
|
+
if (value === undefined || value === null)
|
|
9
|
+
return NaN;
|
|
10
|
+
const n = Number(value);
|
|
11
|
+
if (!Number.isInteger(n))
|
|
12
|
+
return NaN;
|
|
13
|
+
if (n < 1)
|
|
14
|
+
return NaN;
|
|
15
|
+
return n;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* read_file — 读取文件内容
|
|
19
|
+
*
|
|
20
|
+
* 工作区内文件直接读取;工作区外文件需用户确认。
|
|
21
|
+
* 文件大小限制 1 MB,超限返回错误。
|
|
22
|
+
* 支持 offset / limit 按行翻页,不指定时默认读前 500 行。
|
|
23
|
+
*/
|
|
24
|
+
export const readFileTool = {
|
|
25
|
+
name: 'read_file',
|
|
26
|
+
description: 'Read file contents. Supports offset/limit for paginated line-by-line reading. Use for viewing code, config, docs, etc.',
|
|
27
|
+
parameters: {
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: {
|
|
30
|
+
path: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
description: 'File path (relative to workspace or absolute)'
|
|
33
|
+
},
|
|
34
|
+
offset: {
|
|
35
|
+
type: 'integer',
|
|
36
|
+
description: 'Starting line number (1-based), default 1'
|
|
37
|
+
},
|
|
38
|
+
limit: {
|
|
39
|
+
type: 'integer',
|
|
40
|
+
description: 'Max lines to read, default 500'
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
required: ['path']
|
|
44
|
+
},
|
|
45
|
+
async execute(args, ctx) {
|
|
46
|
+
const userPath = args.path;
|
|
47
|
+
if (!userPath) {
|
|
48
|
+
return { success: false, output: '', error: '缺少参数: path' };
|
|
49
|
+
}
|
|
50
|
+
let offset = DEFAULT_OFFSET;
|
|
51
|
+
let limit = DEFAULT_LIMIT;
|
|
52
|
+
if ('offset' in args && args.offset !== undefined && args.offset !== null) {
|
|
53
|
+
const parsed = validateParam('offset', args.offset);
|
|
54
|
+
if (isNaN(parsed)) {
|
|
55
|
+
return { success: false, output: '', error: 'offset 必须是大于等于 1 的整数' };
|
|
56
|
+
}
|
|
57
|
+
offset = parsed;
|
|
58
|
+
}
|
|
59
|
+
if ('limit' in args && args.limit !== undefined && args.limit !== null) {
|
|
60
|
+
const parsed = validateParam('limit', args.limit);
|
|
61
|
+
if (isNaN(parsed)) {
|
|
62
|
+
return { success: false, output: '', error: 'limit 必须是大于等于 1 的整数' };
|
|
63
|
+
}
|
|
64
|
+
limit = parsed;
|
|
65
|
+
}
|
|
66
|
+
const resolved = ctx.resolvePath(userPath);
|
|
67
|
+
const { path: filePath, classification } = resolved;
|
|
68
|
+
if (!args.__confirmed) {
|
|
69
|
+
if (classification === 'reject') {
|
|
70
|
+
return { success: false, output: '', error: `拒绝读取系统路径: ${userPath}` };
|
|
71
|
+
}
|
|
72
|
+
if (classification === 'confirm') {
|
|
73
|
+
throw new PendingConfirmation('read_file', { path: userPath, offset, limit }, `文件 "${userPath}" 在工作区之外,确认读取?`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const info = await stat(filePath);
|
|
78
|
+
if (!info.isFile()) {
|
|
79
|
+
return { success: false, output: '', error: `路径不是文件: ${userPath}` };
|
|
80
|
+
}
|
|
81
|
+
if (info.size > MAX_FILE_SIZE) {
|
|
82
|
+
return {
|
|
83
|
+
success: false,
|
|
84
|
+
output: '',
|
|
85
|
+
error: `文件过大 (${(info.size / 1024 / 1024).toFixed(1)} MB),最大支持 1 MB`
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const rawContent = await readFile(filePath, 'utf-8');
|
|
89
|
+
const content = stripBom(rawContent);
|
|
90
|
+
const lines = content.split('\n');
|
|
91
|
+
const totalLines = lines.length;
|
|
92
|
+
const startIdx = offset - 1;
|
|
93
|
+
if (startIdx >= totalLines) {
|
|
94
|
+
return {
|
|
95
|
+
success: true,
|
|
96
|
+
output: `=== ${userPath} (第 ${offset}-${offset + limit - 1} 行 / 共 ${totalLines} 行) ===\n\n(起始行号超出文件末尾)`
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const endIdx = Math.min(startIdx + limit, totalLines);
|
|
100
|
+
const slice = lines.slice(startIdx, endIdx);
|
|
101
|
+
const atEnd = endIdx >= totalLines;
|
|
102
|
+
const rangeLabel = `(第 ${offset}-${startIdx + slice.length} 行 / 共 ${totalLines} 行${atEnd ? ',已达文件末尾' : ''})`;
|
|
103
|
+
return {
|
|
104
|
+
success: true,
|
|
105
|
+
output: `=== ${userPath} ${rangeLabel} ===\n${slice.join('\n')}`
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
if (error.code === 'ENOENT') {
|
|
110
|
+
return { success: false, output: '', error: `文件不存在: ${userPath}` };
|
|
111
|
+
}
|
|
112
|
+
return { success: false, output: '', error: `读取失败: ${error.message}` };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=read-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-file.js","sourceRoot":"","sources":["../../../src/tool/tools/read-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-memory.d.ts","sourceRoot":"","sources":["../../../src/tool/tools/read-memory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAKvD,eAAO,MAAM,cAAc,EAAE,OA0D5B,CAAC"}
|