@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,58 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { getDataPath } from '../../paths.js';
|
|
3
|
+
const MEMORY_PATH = getDataPath('memory.md');
|
|
4
|
+
export const readMemoryTool = {
|
|
5
|
+
name: 'read_memory',
|
|
6
|
+
description: 'Read long-term memory (data/memory.md). Optionally pass a query for keyword search — returns matching lines with their category headers. Without query, returns the full memory content. Use when you need to recall previously stored information about users, yourself, or important events. Note: the memory snapshot taken at session creation may be stale; this tool always returns the latest.',
|
|
7
|
+
parameters: {
|
|
8
|
+
type: 'object',
|
|
9
|
+
properties: {
|
|
10
|
+
query: {
|
|
11
|
+
type: 'string',
|
|
12
|
+
description: 'Optional. Search keyword (case-insensitive). Returns matching lines with their category headers. Omit to return all memory.'
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
required: []
|
|
16
|
+
},
|
|
17
|
+
async execute(args, _ctx) {
|
|
18
|
+
try {
|
|
19
|
+
if (!existsSync(MEMORY_PATH)) {
|
|
20
|
+
return { success: true, output: '(暂无记忆内容)' };
|
|
21
|
+
}
|
|
22
|
+
const content = readFileSync(MEMORY_PATH, 'utf-8');
|
|
23
|
+
if (!content.trim()) {
|
|
24
|
+
return { success: true, output: '(暂无记忆内容)' };
|
|
25
|
+
}
|
|
26
|
+
const query = args.query;
|
|
27
|
+
if (!query?.trim()) {
|
|
28
|
+
return { success: true, output: content };
|
|
29
|
+
}
|
|
30
|
+
const lines = content.split('\n');
|
|
31
|
+
const lowerQuery = query.trim().toLowerCase();
|
|
32
|
+
const resultLines = [];
|
|
33
|
+
let lastHeader = '';
|
|
34
|
+
for (const line of lines) {
|
|
35
|
+
const isHeader = line.startsWith('## ');
|
|
36
|
+
if (isHeader) {
|
|
37
|
+
lastHeader = line;
|
|
38
|
+
}
|
|
39
|
+
const isContent = line.trim() !== '' && !line.startsWith('## ');
|
|
40
|
+
if (isContent && line.toLowerCase().includes(lowerQuery)) {
|
|
41
|
+
if (lastHeader && !resultLines.includes(lastHeader)) {
|
|
42
|
+
resultLines.push(lastHeader);
|
|
43
|
+
resultLines.push('');
|
|
44
|
+
}
|
|
45
|
+
resultLines.push(line);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (resultLines.length === 0) {
|
|
49
|
+
return { success: true, output: `(记忆中没有找到与 "${query.trim()}" 相关的内容)` };
|
|
50
|
+
}
|
|
51
|
+
return { success: true, output: resultLines.join('\n') };
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
return { success: false, output: '', error: `读取记忆失败: ${error.message}` };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=read-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-memory.js","sourceRoot":"","sources":["../../../src/tool/tools/read-memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-tasks.d.ts","sourceRoot":"","sources":["../../../src/tool/tools/read-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAGvD,eAAO,MAAM,aAAa,EAAE,OA4B3B,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { getAllTasks, formatTasksForAI } from '../../task/index.js';
|
|
2
|
+
export const readTasksTool = {
|
|
3
|
+
name: 'read_tasks',
|
|
4
|
+
description: 'Query scheduled task list and results. View all tasks (pending, running, completed, failed, paused) or filter by status. The AI is NOT automatically notified of completions — you must manually call this tool to check.',
|
|
5
|
+
parameters: {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
status: {
|
|
9
|
+
type: 'string',
|
|
10
|
+
description: 'Filter by status: pending, running, completed, failed, paused. Omit to return all.'
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
required: []
|
|
14
|
+
},
|
|
15
|
+
execute: async (args) => {
|
|
16
|
+
const statusFilter = args.status?.trim();
|
|
17
|
+
let tasks = getAllTasks();
|
|
18
|
+
if (statusFilter) {
|
|
19
|
+
const valid = ['pending', 'running', 'completed', 'failed', 'paused'];
|
|
20
|
+
if (!valid.includes(statusFilter)) {
|
|
21
|
+
return { success: false, output: '', error: `无效的状态值 "${statusFilter}",可选: ${valid.join(', ')}` };
|
|
22
|
+
}
|
|
23
|
+
tasks = tasks.filter((t) => t.status === statusFilter);
|
|
24
|
+
}
|
|
25
|
+
const output = formatTasksForAI(tasks);
|
|
26
|
+
return { success: true, output };
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=read-tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-tasks.js","sourceRoot":"","sources":["../../../src/tool/tools/read-tasks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEpE,MAAM,CAAC,MAAM,aAAa,GAAY;IACrC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,2NAA2N;IACxO,UAAU,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACX,MAAM,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,oFAAoF;aACjG;SACD;QACD,QAAQ,EAAE,EAAE;KACZ;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAuB,EAAE;QAC5C,MAAM,YAAY,GAAI,IAAI,CAAC,MAAiB,EAAE,IAAI,EAAE,CAAC;QACrD,IAAI,KAAK,GAAG,WAAW,EAAE,CAAC;QAE1B,IAAI,YAAY,EAAE,CAAC;YAClB,MAAM,KAAK,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACtE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBACnC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,YAAY,SAAS,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YAClG,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAClC,CAAC;CACD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-task.d.ts","sourceRoot":"","sources":["../../../src/tool/tools/schedule-task.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAGvD,eAAO,MAAM,gBAAgB,EAAE,OAqD9B,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createTask } from '../../task/index.js';
|
|
2
|
+
export const scheduleTaskTool = {
|
|
3
|
+
name: 'schedule_task',
|
|
4
|
+
description: 'Create a scheduled one-shot task. The task runs automatically at the specified future time (no conversation context) and the user is notified on completion. Before using, run exec to get the current system time to ensure scheduledAt is in the future.',
|
|
5
|
+
parameters: {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
name: {
|
|
9
|
+
type: 'string',
|
|
10
|
+
description: 'Task name (short description, e.g. "Data processing")'
|
|
11
|
+
},
|
|
12
|
+
prompt: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: 'Task description — this is the sole instruction the model receives when executing in the background with no conversation context. Must be self-contained: what to do, expected output format, any necessary details'
|
|
15
|
+
},
|
|
16
|
+
scheduledAt: {
|
|
17
|
+
type: 'string',
|
|
18
|
+
description: 'ISO 8601 datetime string (e.g. 2026-06-16T14:30:00Z). Must be in the future. Use exec to get current system time first.'
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
required: ['name', 'prompt', 'scheduledAt']
|
|
22
|
+
},
|
|
23
|
+
execute: async (args) => {
|
|
24
|
+
const name = args.name;
|
|
25
|
+
const prompt = args.prompt;
|
|
26
|
+
const scheduledAtStr = args.scheduledAt;
|
|
27
|
+
if (!name?.trim() || !prompt?.trim() || !scheduledAtStr?.trim()) {
|
|
28
|
+
return { success: false, output: '', error: '参数不完整:name、prompt、scheduledAt 均为必填' };
|
|
29
|
+
}
|
|
30
|
+
const scheduledAt = new Date(scheduledAtStr).getTime();
|
|
31
|
+
if (isNaN(scheduledAt)) {
|
|
32
|
+
return { success: false, output: '', error: `无法解析时间 "${scheduledAtStr}",请使用 ISO 8601 格式,如 2026-06-16T14:30:00Z` };
|
|
33
|
+
}
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
if (scheduledAt <= now) {
|
|
36
|
+
return { success: false, output: '', error: `计划执行时间 ${scheduledAtStr} 已过期。当前时间是 ${new Date(now).toISOString()},请设置一个未来的时间` };
|
|
37
|
+
}
|
|
38
|
+
const maxFuture = now + 30 * 24 * 60 * 60 * 1000;
|
|
39
|
+
if (scheduledAt > maxFuture) {
|
|
40
|
+
return { success: false, output: '', error: `计划执行时间不能超过 30 天后` };
|
|
41
|
+
}
|
|
42
|
+
const task = await createTask(name.trim(), prompt.trim(), scheduledAt);
|
|
43
|
+
const formatted = new Date(scheduledAt).toISOString().replace('T', ' ').slice(0, 19);
|
|
44
|
+
return {
|
|
45
|
+
success: true,
|
|
46
|
+
output: `任务已创建:\n- ID: ${task.id.slice(0, 8)}\n- 名称: ${task.name}\n- 计划执行: ${formatted}\n\n任务将在指定时间自动执行,完成后通过 Email 通知你。`
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=schedule-task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-task.js","sourceRoot":"","sources":["../../../src/tool/tools/schedule-task.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,CAAC,MAAM,gBAAgB,GAAY;IACxC,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,4PAA4P;IACzQ,UAAU,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACX,IAAI,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,uDAAuD;aACpE;YACD,MAAM,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,qNAAqN;aAClO;YACD,WAAW,EAAE;gBACZ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,yHAAyH;aACtI;SACD;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC;KAC3C;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAuB,EAAE;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAc,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAgB,CAAC;QACrC,MAAM,cAAc,GAAG,IAAI,CAAC,WAAqB,CAAC;QAElD,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC;YACjE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC;QACpF,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;QACvD,IAAI,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;YACxB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,cAAc,0CAA0C,EAAE,CAAC;QACnH,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,WAAW,IAAI,GAAG,EAAE,CAAC;YACxB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,cAAc,cAAc,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,aAAa,EAAE,CAAC;QAC9H,CAAC;QAED,MAAM,SAAS,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QACjD,IAAI,WAAW,GAAG,SAAS,EAAE,CAAC;YAC7B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;QAClE,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,WAAW,CAAC,CAAC;QACvE,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAErF,OAAO;YACN,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,iBAAiB,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,WAAW,IAAI,CAAC,IAAI,aAAa,SAAS,mCAAmC;SACzH,CAAC;IACH,CAAC;CACD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-history.d.ts","sourceRoot":"","sources":["../../../src/tool/tools/search-history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAuB,MAAM,wBAAwB,CAAC;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAwBvD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAwCjE"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
function formatResults(results, query) {
|
|
2
|
+
if (results.length === 0) {
|
|
3
|
+
return `(未在历史对话中找到与 "${query}" 相关的内容)`;
|
|
4
|
+
}
|
|
5
|
+
const lines = [`找到 ${results.length} 条与 "${query}" 相关的结果:`];
|
|
6
|
+
let lastSession = '';
|
|
7
|
+
for (const r of results) {
|
|
8
|
+
if (r.sessionTitle !== lastSession) {
|
|
9
|
+
lastSession = r.sessionTitle;
|
|
10
|
+
lines.push('', `--- ${r.sessionTitle} ---`);
|
|
11
|
+
}
|
|
12
|
+
const date = new Date(r.createdAt).toLocaleString('zh-CN');
|
|
13
|
+
const roleLabel = r.role === 'user' ? '用户' : r.role === 'assistant' ? 'AI' : r.role;
|
|
14
|
+
const snippet = r.content.length > 200 ? r.content.slice(0, 200) + '...' : r.content;
|
|
15
|
+
lines.push(`[${date}] ${roleLabel}: ${snippet}`);
|
|
16
|
+
}
|
|
17
|
+
return lines.join('\n');
|
|
18
|
+
}
|
|
19
|
+
export function createSearchHistoryTool(storage) {
|
|
20
|
+
return {
|
|
21
|
+
name: 'search_history',
|
|
22
|
+
description: 'Search conversation history across all sessions with fuzzy text matching. Use when you need to recall what the user discussed before. Note: this searches chat records, not long-term memory (use read_memory for that).',
|
|
23
|
+
parameters: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: {
|
|
26
|
+
query: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'Search keyword or phrase (case-insensitive). Matches content field of all messages.'
|
|
29
|
+
},
|
|
30
|
+
session_id: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
description: 'Optional. Limit search to a specific session. Omit to search all sessions.'
|
|
33
|
+
},
|
|
34
|
+
limit: {
|
|
35
|
+
type: 'number',
|
|
36
|
+
description: 'Optional. Max results, default 10.'
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
required: ['query']
|
|
40
|
+
},
|
|
41
|
+
async execute(args, _ctx) {
|
|
42
|
+
const query = args.query;
|
|
43
|
+
const sessionId = args.session_id;
|
|
44
|
+
const limit = args.limit || 10;
|
|
45
|
+
if (!query?.trim()) {
|
|
46
|
+
return { success: false, output: '', error: 'query 不能为空' };
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const results = await storage.searchMessages(query.trim(), sessionId || undefined, limit);
|
|
50
|
+
return { success: true, output: formatResults(results, query.trim()) };
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
return { success: false, output: '', error: `搜索失败: ${error.message}` };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=search-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-history.js","sourceRoot":"","sources":["../../../src/tool/tools/search-history.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search.d.ts","sourceRoot":"","sources":["../../../src/tool/tools/web-search.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAyCvD,eAAO,MAAM,aAAa,EAAE,OAiE3B,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { readConfig } from '../../config/index.js';
|
|
2
|
+
async function searchSearXNG(query, num, baseURL) {
|
|
3
|
+
const url = `${baseURL.replace(/\/+$/, '')}/search?format=json&q=${encodeURIComponent(query)}`;
|
|
4
|
+
const res = await fetch(url);
|
|
5
|
+
if (!res.ok) {
|
|
6
|
+
throw new Error(`SearXNG returned ${res.status}`);
|
|
7
|
+
}
|
|
8
|
+
const json = await res.json();
|
|
9
|
+
const results = json.results || [];
|
|
10
|
+
return results.slice(0, num).map((r) => ({
|
|
11
|
+
title: r.title,
|
|
12
|
+
url: r.url,
|
|
13
|
+
snippet: r.content || ''
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
async function searchTavily(query, num, apiKey) {
|
|
17
|
+
const res = await fetch('https://api.tavily.com/search', {
|
|
18
|
+
method: 'POST',
|
|
19
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },
|
|
20
|
+
body: JSON.stringify({ query, max_results: num, include_answer: false })
|
|
21
|
+
});
|
|
22
|
+
if (!res.ok) {
|
|
23
|
+
throw new Error(`Tavily returned ${res.status}`);
|
|
24
|
+
}
|
|
25
|
+
const json = await res.json();
|
|
26
|
+
const results = json.results || [];
|
|
27
|
+
return results.slice(0, num).map((r) => ({
|
|
28
|
+
title: r.title,
|
|
29
|
+
url: r.url,
|
|
30
|
+
snippet: r.content || ''
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
export const webSearchTool = {
|
|
34
|
+
name: 'web_search',
|
|
35
|
+
description: 'Search the internet for information. Use for latest news, documentation lookup, fact verification, etc. Only use when real-time or external knowledge is needed. Results include title, URL, and snippet.',
|
|
36
|
+
parameters: {
|
|
37
|
+
type: 'object',
|
|
38
|
+
properties: {
|
|
39
|
+
query: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
description: 'Search query (keyword or question)'
|
|
42
|
+
},
|
|
43
|
+
num: {
|
|
44
|
+
type: 'integer',
|
|
45
|
+
description: 'Number of results, default 5, max 10'
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
required: ['query']
|
|
49
|
+
},
|
|
50
|
+
async execute(args, _ctx) {
|
|
51
|
+
const query = args.query?.trim();
|
|
52
|
+
if (!query) {
|
|
53
|
+
return { success: false, output: '', error: '缺少参数: query' };
|
|
54
|
+
}
|
|
55
|
+
const num = Math.min(Math.max(typeof args.num === 'number' ? args.num : 5, 1), 10);
|
|
56
|
+
const config = readConfig();
|
|
57
|
+
if (!config.searchEnabled) {
|
|
58
|
+
return { success: false, output: '', error: '搜索功能未启用,请在设置中开启' };
|
|
59
|
+
}
|
|
60
|
+
const provider = config.searchProvider || 'searxng';
|
|
61
|
+
try {
|
|
62
|
+
let results;
|
|
63
|
+
if (provider === 'tavily') {
|
|
64
|
+
if (!config.tavilyApiKey) {
|
|
65
|
+
return { success: false, output: '', error: '未配置 Tavily API Key,请在设置中填写' };
|
|
66
|
+
}
|
|
67
|
+
results = await searchTavily(query, num, config.tavilyApiKey);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const searxngURL = config.searxngURL || 'http://localhost:8080';
|
|
71
|
+
results = await searchSearXNG(query, num, searxngURL);
|
|
72
|
+
}
|
|
73
|
+
if (results.length === 0) {
|
|
74
|
+
return { success: true, output: `未找到与「${query}」相关的结果。` };
|
|
75
|
+
}
|
|
76
|
+
const formatted = results
|
|
77
|
+
.map((r, i) => `${i + 1}. **[${r.title}](${r.url})**\n ${r.snippet}`)
|
|
78
|
+
.join('\n\n');
|
|
79
|
+
return {
|
|
80
|
+
success: true,
|
|
81
|
+
output: `搜索「${query}」的结果(共 ${results.length} 条):\n\n${formatted}`
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
return { success: false, output: '', error: `搜索失败: ${error.message}` };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=web-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search.js","sourceRoot":"","sources":["../../../src/tool/tools/web-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ToolDef } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* write_file — 写入文件内容
|
|
4
|
+
*
|
|
5
|
+
* 自动创建不存在的父目录。覆盖已有文件。
|
|
6
|
+
* 使用原子写入(临时文件 + rename),崩溃时不留残缺文件。
|
|
7
|
+
* 覆盖已有文件时自动保留原文件的 BOM 和行尾格式(CRLF/LF)。
|
|
8
|
+
* 工作区内文件直接写入;工作区外需用户确认。
|
|
9
|
+
*/
|
|
10
|
+
export declare const writeFileTool: ToolDef;
|
|
11
|
+
//# sourceMappingURL=write-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-file.d.ts","sourceRoot":"","sources":["../../../src/tool/tools/write-file.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAKvD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,OA4E3B,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { readFile, mkdir, stat } from 'node:fs/promises';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { PendingConfirmation } from '../types.js';
|
|
4
|
+
import { detectMeta, atomicWrite } from './file-utils.js';
|
|
5
|
+
/**
|
|
6
|
+
* write_file — 写入文件内容
|
|
7
|
+
*
|
|
8
|
+
* 自动创建不存在的父目录。覆盖已有文件。
|
|
9
|
+
* 使用原子写入(临时文件 + rename),崩溃时不留残缺文件。
|
|
10
|
+
* 覆盖已有文件时自动保留原文件的 BOM 和行尾格式(CRLF/LF)。
|
|
11
|
+
* 工作区内文件直接写入;工作区外需用户确认。
|
|
12
|
+
*/
|
|
13
|
+
export const writeFileTool = {
|
|
14
|
+
name: 'write_file',
|
|
15
|
+
description: 'Write content to a file (overwrites). Creates missing parent directories automatically. Preserves existing file encoding (BOM, line endings) when overwriting.',
|
|
16
|
+
parameters: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
path: {
|
|
20
|
+
type: 'string',
|
|
21
|
+
description: 'File path (relative to workspace or absolute)'
|
|
22
|
+
},
|
|
23
|
+
content: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
description: 'Complete file content to write'
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
required: ['path', 'content']
|
|
29
|
+
},
|
|
30
|
+
async execute(args, ctx) {
|
|
31
|
+
const userPath = args.path;
|
|
32
|
+
const content = args.content;
|
|
33
|
+
if (!userPath) {
|
|
34
|
+
return { success: false, output: '', error: '缺少参数: path' };
|
|
35
|
+
}
|
|
36
|
+
if (content === undefined || content === null) {
|
|
37
|
+
return { success: false, output: '', error: '缺少参数: content' };
|
|
38
|
+
}
|
|
39
|
+
const resolved = ctx.resolvePath(userPath);
|
|
40
|
+
const { path: filePath, classification } = resolved;
|
|
41
|
+
if (!args.__confirmed) {
|
|
42
|
+
if (classification === 'reject') {
|
|
43
|
+
return { success: false, output: '', error: `拒绝写入系统路径: ${userPath}` };
|
|
44
|
+
}
|
|
45
|
+
if (classification === 'confirm') {
|
|
46
|
+
throw new PendingConfirmation('write_file', { path: userPath, content }, `文件 "${userPath}" 在工作区之外,确认写入?`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
51
|
+
let existed = false;
|
|
52
|
+
let meta = undefined;
|
|
53
|
+
try {
|
|
54
|
+
const info = await stat(filePath);
|
|
55
|
+
existed = info.isFile();
|
|
56
|
+
if (existed) {
|
|
57
|
+
const raw = await readFile(filePath, 'utf-8');
|
|
58
|
+
meta = detectMeta(raw);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// new file
|
|
63
|
+
}
|
|
64
|
+
await atomicWrite(filePath, content, meta);
|
|
65
|
+
const action = existed ? '已更新' : '已创建';
|
|
66
|
+
const lines = content.split('\n').length;
|
|
67
|
+
const bytes = Buffer.byteLength(content, 'utf-8');
|
|
68
|
+
const metaNote = meta?.bom ? ' (已保留 BOM)' : '';
|
|
69
|
+
return {
|
|
70
|
+
success: true,
|
|
71
|
+
output: `${action}文件: ${userPath} (${lines} 行, ${bytes} 字节${metaNote})`
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
return { success: false, output: '', error: `写入失败: ${error.message}` };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=write-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-file.js","sourceRoot":"","sources":["../../../src/tool/tools/write-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAY;IACrC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,gKAAgK;IAC7K,UAAU,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACX,IAAI,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,+CAA+C;aAC5D;YACD,OAAO,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,gCAAgC;aAC7C;SACD;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;KAC7B;IAED,KAAK,CAAC,OAAO,CAAC,IAA6B,EAAE,GAAgB;QAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAc,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAiB,CAAC;QAEvC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;QAC5D,CAAC;QACD,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YAC/C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;QAC/D,CAAC;QAED,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC;QAEpD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACvB,IAAI,cAAc,KAAK,QAAQ,EAAE,CAAC;gBACjC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,aAAa,QAAQ,EAAE,EAAE,CAAC;YACvE,CAAC;YACD,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBAClC,MAAM,IAAI,mBAAmB,CAC5B,YAAY,EACZ,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAC3B,OAAO,QAAQ,gBAAgB,CAC/B,CAAC;YACH,CAAC;QACF,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAEpD,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,IAAI,IAAI,GAAG,SAAS,CAAC;YACrB,IAAI,CAAC;gBACJ,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAClC,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;gBACxB,IAAI,OAAO,EAAE,CAAC;oBACb,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;oBAC9C,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;gBACxB,CAAC;YACF,CAAC;YAAC,MAAM,CAAC;gBACR,WAAW;YACZ,CAAC;YAED,MAAM,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YAE3C,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;YACvC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;YACzC,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAClD,MAAM,QAAQ,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;YAE/C,OAAO;gBACN,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,GAAG,MAAM,OAAO,QAAQ,KAAK,KAAK,OAAO,KAAK,MAAM,QAAQ,GAAG;aACvE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,SAAU,KAAe,CAAC,OAAO,EAAE,EAAE,CAAC;QACnF,CAAC;IACF,CAAC;CACD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-memory.d.ts","sourceRoot":"","sources":["../../../src/tool/tools/write-memory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AA+DvD,eAAO,MAAM,eAAe,EAAE,OA6C7B,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { getDataDir, getDataPath } from '../../paths.js';
|
|
3
|
+
const SECTION_META = `
|
|
4
|
+
## 关于我自己 (Qualia)
|
|
5
|
+
我是一个运行在本地环境中的 AI 伴侣,帮助用户完成开发工作和日常任务。
|
|
6
|
+
|
|
7
|
+
## 关于用户
|
|
8
|
+
(待记录)
|
|
9
|
+
|
|
10
|
+
## 重要事件
|
|
11
|
+
(待记录)
|
|
12
|
+
`;
|
|
13
|
+
const MEMORY_PATH = getDataPath('memory.md');
|
|
14
|
+
function ensureMemoryFile() {
|
|
15
|
+
const dir = getDataDir();
|
|
16
|
+
if (!existsSync(dir)) {
|
|
17
|
+
mkdirSync(dir, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
if (!existsSync(MEMORY_PATH) || !readFileSync(MEMORY_PATH, 'utf-8').includes('## 关于用户')) {
|
|
20
|
+
writeFileSync(MEMORY_PATH, SECTION_META.trim().replace(/\r/g, '') + '\n', 'utf-8');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const CATEGORY_HEADERS = {
|
|
24
|
+
self: '## 关于我自己 (Qualia)',
|
|
25
|
+
user: '## 关于用户',
|
|
26
|
+
event: '## 重要事件'
|
|
27
|
+
};
|
|
28
|
+
function updateSection(current, category, content) {
|
|
29
|
+
const header = CATEGORY_HEADERS[category];
|
|
30
|
+
if (!header)
|
|
31
|
+
return current;
|
|
32
|
+
const sections = ['self', 'user', 'event'];
|
|
33
|
+
const idx = sections.indexOf(category);
|
|
34
|
+
let result = '';
|
|
35
|
+
let inTarget = false;
|
|
36
|
+
let done = false;
|
|
37
|
+
for (const line of current.split('\n')) {
|
|
38
|
+
const isHeader = line.startsWith('## ');
|
|
39
|
+
if (isHeader) {
|
|
40
|
+
if (inTarget) {
|
|
41
|
+
result += content + '\n\n';
|
|
42
|
+
done = true;
|
|
43
|
+
}
|
|
44
|
+
inTarget = (line === header);
|
|
45
|
+
}
|
|
46
|
+
else if (inTarget && !done) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
result += line + '\n';
|
|
50
|
+
}
|
|
51
|
+
if (inTarget && !done) {
|
|
52
|
+
result += content;
|
|
53
|
+
}
|
|
54
|
+
return result.trim() + '\n';
|
|
55
|
+
}
|
|
56
|
+
export const writeMemoryTool = {
|
|
57
|
+
name: 'write_memory',
|
|
58
|
+
description: 'Write important information to long-term memory (memory.md). Only use for information worth remembering long-term. Content is automatically injected into the system prompt of future sessions. Three categories: self (about yourself), user (about the user), event (important milestones). Each call overwrites the entire content of the given category.',
|
|
59
|
+
parameters: {
|
|
60
|
+
type: 'object',
|
|
61
|
+
properties: {
|
|
62
|
+
category: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
description: 'Memory category: self (about yourself), user (about the user), event (important events)',
|
|
65
|
+
enum: ['self', 'user', 'event']
|
|
66
|
+
},
|
|
67
|
+
content: {
|
|
68
|
+
type: 'string',
|
|
69
|
+
description: 'New content for this category (replaces existing). Write in Chinese, concise and brief, one item per line.'
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
required: ['category', 'content']
|
|
73
|
+
},
|
|
74
|
+
async execute(args, _ctx) {
|
|
75
|
+
const category = args.category;
|
|
76
|
+
const content = args.content;
|
|
77
|
+
if (!category || !CATEGORY_HEADERS[category]) {
|
|
78
|
+
return { success: false, output: '', error: `无效的类别: ${category},可选: self, user, event` };
|
|
79
|
+
}
|
|
80
|
+
if (!content?.trim()) {
|
|
81
|
+
return { success: false, output: '', error: 'content 不能为空' };
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
ensureMemoryFile();
|
|
85
|
+
const current = readFileSync(MEMORY_PATH, 'utf-8').replace(/\r/g, '');
|
|
86
|
+
const updated = updateSection(current, category, content.trim());
|
|
87
|
+
writeFileSync(MEMORY_PATH, updated, 'utf-8');
|
|
88
|
+
const header = CATEGORY_HEADERS[category];
|
|
89
|
+
return {
|
|
90
|
+
success: true,
|
|
91
|
+
output: `已更新记忆: ${header}\n${content}`
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
return { success: false, output: '', error: `写入失败: ${error.message}` };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=write-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-memory.js","sourceRoot":"","sources":["../../../src/tool/tools/write-memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ToolContext } from './env.js';
|
|
2
|
+
/**
|
|
3
|
+
* 工具定义接口
|
|
4
|
+
*
|
|
5
|
+
* 每个工具实现此接口,包含名称、描述、参数 schema 和执行逻辑。
|
|
6
|
+
*/
|
|
7
|
+
export interface ToolDef {
|
|
8
|
+
/** 工具名称,用于 LLM function calling 和注册表查找 */
|
|
9
|
+
name: string;
|
|
10
|
+
/** 工具描述,用于 LLM 理解功能 */
|
|
11
|
+
description: string;
|
|
12
|
+
/** JSON Schema 参数定义 */
|
|
13
|
+
parameters: Record<string, unknown>;
|
|
14
|
+
/**
|
|
15
|
+
* 执行工具
|
|
16
|
+
* @param args - 调用参数
|
|
17
|
+
* @param ctx - 工具执行上下文(工作区根目录、路径安全等)
|
|
18
|
+
* @returns 执行结果
|
|
19
|
+
* @throws PendingConfirmation 当需要用户确认时
|
|
20
|
+
*/
|
|
21
|
+
execute(args: Record<string, unknown>, ctx: ToolContext): Promise<ToolResult>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 工具执行结果
|
|
25
|
+
*/
|
|
26
|
+
export interface ToolResult {
|
|
27
|
+
/** 是否成功 */
|
|
28
|
+
success: boolean;
|
|
29
|
+
/** 输出内容 */
|
|
30
|
+
output: string;
|
|
31
|
+
/** 错误描述(success 为 false 时填充) */
|
|
32
|
+
error?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 待确认异常
|
|
36
|
+
*
|
|
37
|
+
* 工具执行时如需要用户确认,抛出此异常。
|
|
38
|
+
* 上层 Agent Loop 捕获后通过 SSE 推送确认请求到前端,
|
|
39
|
+
* 用户确认后以 __confirmed: true 重新调用工具。
|
|
40
|
+
*/
|
|
41
|
+
export declare class PendingConfirmation extends Error {
|
|
42
|
+
/** 工具名称 */
|
|
43
|
+
toolName: string;
|
|
44
|
+
/** 调用参数 */
|
|
45
|
+
args: Record<string, unknown>;
|
|
46
|
+
/** 需要确认的原因 */
|
|
47
|
+
reason: string;
|
|
48
|
+
constructor(
|
|
49
|
+
/** 工具名称 */
|
|
50
|
+
toolName: string,
|
|
51
|
+
/** 调用参数 */
|
|
52
|
+
args: Record<string, unknown>,
|
|
53
|
+
/** 需要确认的原因 */
|
|
54
|
+
reason: string);
|
|
55
|
+
toJSON(): {
|
|
56
|
+
toolName: string;
|
|
57
|
+
args: Record<string, unknown>;
|
|
58
|
+
reason: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** 命令安全分类 */
|
|
62
|
+
export type CommandClassification = 'safe' | 'confirm' | 'reject';
|
|
63
|
+
//# sourceMappingURL=types.d.ts.map
|