zhitalk 0.0.5 → 0.0.7
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/README.md +2 -2
- package/dist/agent/agent.js +86 -63
- package/dist/agent/cli.js +39 -73
- package/dist/agent/colors.js +6 -44
- package/dist/agent/commands.js +22 -28
- package/dist/agent/config.js +20 -62
- package/dist/agent/context.js +14 -12
- package/dist/agent/db.js +17 -27
- package/dist/agent/hooks.d.ts +1 -1
- package/dist/agent/hooks.js +13 -22
- package/dist/agent/mcp/client.js +25 -29
- package/dist/agent/mcp/index.d.ts +1 -1
- package/dist/agent/mcp/index.js +8 -13
- package/dist/agent/mcp/wrapper.d.ts +2 -2
- package/dist/agent/mcp/wrapper.js +5 -8
- package/dist/agent/model.js +6 -10
- package/dist/agent/permission/exec.js +8 -11
- package/dist/agent/permission/is-dangerous-path.js +126 -18
- package/dist/agent/permission/is-safe-domains.js +1 -4
- package/dist/agent/permission/network.js +3 -6
- package/dist/agent/permission/read.js +3 -6
- package/dist/agent/permission/util.js +16 -26
- package/dist/agent/permission/write.js +5 -8
- package/dist/agent/prompt.js +9 -15
- package/dist/agent/skills.js +19 -24
- package/dist/agent/tools/agent_tool.js +2 -38
- package/dist/agent/tools/exec_tool.js +4 -7
- package/dist/agent/tools/load_skill_tool.js +3 -6
- package/dist/agent/tools/memory_create_tool.js +4 -10
- package/dist/agent/tools/memory_delete_tool.js +4 -10
- package/dist/agent/tools/memory_retrieve_tool.js +3 -6
- package/dist/agent/tools/profile_update_tool.js +11 -14
- package/dist/agent/tools/read_file_tool.js +4 -6
- package/dist/agent/tools/run_js_tool.js +3 -6
- package/dist/agent/tools/run_py_tool.js +4 -7
- package/dist/agent/tools/search.js +1 -4
- package/dist/agent/tools/web_fetch_tool.js +1 -4
- package/dist/agent/tools/web_search_tool.js +5 -8
- package/dist/agent/tools/write_file_tool.js +8 -9
- package/dist/agent/tools.js +76 -81
- package/dist/agent/utils.d.ts +1 -0
- package/dist/agent/utils.js +13 -6
- package/dist/index.js +23 -49
- package/dist/install.js +14 -50
- package/jest.config.js +11 -0
- package/package.json +8 -7
- package/dist/agent/permission/dangerous-path.json +0 -115
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const promises_1 = require("fs/promises");
|
|
5
|
-
const path_1 = require("path");
|
|
6
|
-
const config_1 = require("../config");
|
|
1
|
+
import { writeFile, readFile, mkdir, copyFile } from 'fs/promises';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
import { WORKSPACE_DIR } from '../config.js';
|
|
7
4
|
function getProfilePaths() {
|
|
8
|
-
const dir =
|
|
9
|
-
return { dir, path:
|
|
5
|
+
const dir = resolve(WORKSPACE_DIR, '.data');
|
|
6
|
+
return { dir, path: resolve(dir, 'profile.md') };
|
|
10
7
|
}
|
|
11
8
|
function generateBackupFilename() {
|
|
12
9
|
const dt = Date.now();
|
|
13
10
|
const random = Math.random().toString(36).slice(2, 8);
|
|
14
11
|
return `profile.${dt}-${random}.md`;
|
|
15
12
|
}
|
|
16
|
-
async function profileUpdateTool({ profile_info, }) {
|
|
13
|
+
export async function profileUpdateTool({ profile_info, }) {
|
|
17
14
|
if (!profile_info || profile_info.trim().length === 0) {
|
|
18
15
|
return 'Error: profile_info is empty.';
|
|
19
16
|
}
|
|
@@ -22,7 +19,7 @@ async function profileUpdateTool({ profile_info, }) {
|
|
|
22
19
|
let existingContent = '';
|
|
23
20
|
let fileExists = false;
|
|
24
21
|
try {
|
|
25
|
-
existingContent = await
|
|
22
|
+
existingContent = await readFile(profilePath, 'utf-8');
|
|
26
23
|
fileExists = true;
|
|
27
24
|
}
|
|
28
25
|
catch (err) {
|
|
@@ -35,13 +32,13 @@ async function profileUpdateTool({ profile_info, }) {
|
|
|
35
32
|
if (fileExists && normalizedNew === normalizedExisting) {
|
|
36
33
|
return 'Profile is already up to date. No changes made.';
|
|
37
34
|
}
|
|
38
|
-
await
|
|
35
|
+
await mkdir(profileDir, { recursive: true });
|
|
39
36
|
if (fileExists) {
|
|
40
37
|
const backupFilename = generateBackupFilename();
|
|
41
|
-
const backupPath =
|
|
42
|
-
await
|
|
38
|
+
const backupPath = resolve(profileDir, backupFilename);
|
|
39
|
+
await copyFile(profilePath, backupPath);
|
|
43
40
|
}
|
|
44
|
-
await
|
|
41
|
+
await writeFile(profilePath, profile_info, 'utf-8');
|
|
45
42
|
return `Profile updated successfully. File: ${profilePath}${fileExists ? ' (backup created)' : ''}`;
|
|
46
43
|
}
|
|
47
44
|
catch (err) {
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const promises_1 = require("fs/promises");
|
|
5
|
-
async function readFileTool({ filepath }) {
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
import { resolvePath } from '../utils.js';
|
|
3
|
+
export async function readFileTool({ filepath }) {
|
|
6
4
|
try {
|
|
7
|
-
const content = await
|
|
5
|
+
const content = await readFile(resolvePath(filepath), 'utf-8');
|
|
8
6
|
return content;
|
|
9
7
|
}
|
|
10
8
|
catch (err) {
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.runJsTool = runJsTool;
|
|
4
|
-
const child_process_1 = require("child_process");
|
|
5
|
-
async function runJsTool({ code }) {
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
export async function runJsTool({ code }) {
|
|
6
3
|
if (!code.trim()) {
|
|
7
4
|
return 'Error: code is empty.';
|
|
8
5
|
}
|
|
9
6
|
return new Promise((resolve) => {
|
|
10
|
-
const child =
|
|
7
|
+
const child = spawn('node', ['--input-type=module'], {
|
|
11
8
|
env: { ...process.env, NO_COLOR: '1', FORCE_COLOR: '0' },
|
|
12
9
|
});
|
|
13
10
|
let stdout = '';
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const util_1 = require("util");
|
|
6
|
-
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
7
|
-
async function runPyTool({ code }) {
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
const execAsync = promisify(exec);
|
|
4
|
+
export async function runPyTool({ code }) {
|
|
8
5
|
const trimmed = code.trim();
|
|
9
6
|
if (!trimmed) {
|
|
10
7
|
return 'Error: code is empty.';
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.search = search;
|
|
4
|
-
async function search({ query }) {
|
|
1
|
+
export async function search({ query }) {
|
|
5
2
|
if (query.toLowerCase().includes('sf') ||
|
|
6
3
|
query.toLowerCase().includes('san francisco')) {
|
|
7
4
|
return "It's 60 degrees and foggy.";
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.webFetchTool = webFetchTool;
|
|
4
1
|
const MAX_LENGTH = 8000;
|
|
5
|
-
async function webFetchTool({ url }) {
|
|
2
|
+
export async function webFetchTool({ url }) {
|
|
6
3
|
const trimmed = url.trim();
|
|
7
4
|
if (!trimmed) {
|
|
8
5
|
return 'Error: url is empty.';
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const config_1 = require("../config");
|
|
6
|
-
async function webSearchTool({ query }) {
|
|
7
|
-
const tavilyApiKey = (0, config_1.getEnv)('TAVILY_API_KEY');
|
|
1
|
+
import { TavilySearch } from '@langchain/tavily';
|
|
2
|
+
import { getEnv } from '../config.js';
|
|
3
|
+
export async function webSearchTool({ query }) {
|
|
4
|
+
const tavilyApiKey = getEnv('TAVILY_API_KEY');
|
|
8
5
|
if (!tavilyApiKey) {
|
|
9
6
|
return 'Error: 未配置 TAVILY_API_KEY。请在 ~/.zhitalk/zhitalk.json 的 env 中设置 TAVILY_API_KEY。';
|
|
10
7
|
}
|
|
11
|
-
const tavilySearch = new
|
|
8
|
+
const tavilySearch = new TavilySearch({
|
|
12
9
|
maxResults: 3,
|
|
13
10
|
topic: 'general',
|
|
14
11
|
tavilyApiKey,
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const path_1 = require("path");
|
|
6
|
-
async function writeFileTool({ filepath, content }) {
|
|
1
|
+
import { writeFile, mkdir } from 'fs/promises';
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
import { resolvePath } from '../utils.js';
|
|
4
|
+
export async function writeFileTool({ filepath, content }) {
|
|
7
5
|
try {
|
|
8
|
-
|
|
9
|
-
await (
|
|
10
|
-
|
|
6
|
+
const absolutePath = resolvePath(filepath);
|
|
7
|
+
await mkdir(dirname(absolutePath), { recursive: true });
|
|
8
|
+
await writeFile(absolutePath, content, 'utf-8');
|
|
9
|
+
return `File "${absolutePath}" written successfully.`;
|
|
11
10
|
}
|
|
12
11
|
catch (err) {
|
|
13
12
|
return `Error: ${err.message}`;
|
package/dist/agent/tools.js
CHANGED
|
@@ -1,104 +1,99 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const memory_retrieve_tool_1 = require("./tools/memory_retrieve_tool");
|
|
21
|
-
const memory_delete_tool_1 = require("./tools/memory_delete_tool");
|
|
22
|
-
const profile_update_tool_1 = require("./tools/profile_update_tool");
|
|
23
|
-
const agent_tool_1 = require("./tools/agent_tool");
|
|
24
|
-
const mcp_1 = require("./mcp");
|
|
1
|
+
import { tool } from '@langchain/core/tools';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { mkdir, writeFile } from 'fs/promises';
|
|
4
|
+
import { resolve } from 'path';
|
|
5
|
+
import { WORKSPACE_DIR } from './config.js';
|
|
6
|
+
import { readFileTool as readFileToolImpl } from './tools/read_file_tool.js';
|
|
7
|
+
import { writeFileTool as writeFileToolImpl } from './tools/write_file_tool.js';
|
|
8
|
+
import { execTool as execToolImpl } from './tools/exec_tool.js';
|
|
9
|
+
import { runJsTool as runJsToolImpl } from './tools/run_js_tool.js';
|
|
10
|
+
import { runPyTool as runPyToolImpl } from './tools/run_py_tool.js';
|
|
11
|
+
import { webSearchTool as webSearchToolImpl } from './tools/web_search_tool.js';
|
|
12
|
+
import { webFetchTool as webFetchToolImpl } from './tools/web_fetch_tool.js';
|
|
13
|
+
import { loadSkillTool as loadSkillToolImpl } from './tools/load_skill_tool.js';
|
|
14
|
+
import { memoryCreateTool as memoryCreateToolImpl } from './tools/memory_create_tool.js';
|
|
15
|
+
import { memoryRetrieveTool as memoryRetrieveToolImpl } from './tools/memory_retrieve_tool.js';
|
|
16
|
+
import { memoryDeleteTool as memoryDeleteToolImpl } from './tools/memory_delete_tool.js';
|
|
17
|
+
import { profileUpdateTool as profileUpdateToolImpl } from './tools/profile_update_tool.js';
|
|
18
|
+
import { agentTool as agentToolImpl } from './tools/agent_tool.js';
|
|
19
|
+
import { initMcpTools } from './mcp/index.js';
|
|
25
20
|
function createZhitalkTool(impl, options, permission_level) {
|
|
26
|
-
const t =
|
|
21
|
+
const t = tool(impl, options);
|
|
27
22
|
t.permission_level = permission_level;
|
|
28
23
|
return t;
|
|
29
24
|
}
|
|
30
|
-
const readFileTool = createZhitalkTool(
|
|
25
|
+
const readFileTool = createZhitalkTool(readFileToolImpl, {
|
|
31
26
|
name: 'read_file',
|
|
32
27
|
description: 'Read the contents of a file.',
|
|
33
|
-
schema:
|
|
34
|
-
filepath:
|
|
28
|
+
schema: z.object({
|
|
29
|
+
filepath: z.string().describe('The path of the file to read. Can be relative, absolute, or start with ~.'),
|
|
35
30
|
}),
|
|
36
31
|
}, 'read');
|
|
37
|
-
const writeFileTool = createZhitalkTool(
|
|
32
|
+
const writeFileTool = createZhitalkTool(writeFileToolImpl, {
|
|
38
33
|
name: 'write_file',
|
|
39
34
|
description: 'Create or overwrite a file. Will create parent directories if needed.',
|
|
40
|
-
schema:
|
|
41
|
-
filepath:
|
|
42
|
-
content:
|
|
35
|
+
schema: z.object({
|
|
36
|
+
filepath: z.string().describe('The path of the file to write. Can be relative, absolute, or start with ~.'),
|
|
37
|
+
content: z.string().describe('The content to write to the file.'),
|
|
43
38
|
}),
|
|
44
39
|
}, 'write');
|
|
45
|
-
const execTool = createZhitalkTool(
|
|
40
|
+
const execTool = createZhitalkTool(execToolImpl, {
|
|
46
41
|
name: 'exec',
|
|
47
42
|
description: 'Execute a safe shell command in the current directory. Dangerous commands (rm, rmdir, etc.), absolute paths, and parent directory references are blocked.',
|
|
48
|
-
schema:
|
|
49
|
-
command:
|
|
43
|
+
schema: z.object({
|
|
44
|
+
command: z.string().describe('The shell command to execute.'),
|
|
50
45
|
}),
|
|
51
46
|
}, 'exec');
|
|
52
|
-
const runJsTool = createZhitalkTool(
|
|
47
|
+
const runJsTool = createZhitalkTool(runJsToolImpl, {
|
|
53
48
|
name: 'run_js',
|
|
54
49
|
description: 'Execute JavaScript code using Node.js in the current directory. Returns stdout/stderr or error messages.',
|
|
55
|
-
schema:
|
|
56
|
-
code:
|
|
50
|
+
schema: z.object({
|
|
51
|
+
code: z.string().describe('The JavaScript code to execute.'),
|
|
57
52
|
}),
|
|
58
53
|
}, 'exec');
|
|
59
|
-
const runPyTool = createZhitalkTool(
|
|
54
|
+
const runPyTool = createZhitalkTool(runPyToolImpl, {
|
|
60
55
|
name: 'run_py',
|
|
61
56
|
description: 'Execute Python code using Python3 in the current directory. Returns stdout/stderr or error messages.',
|
|
62
|
-
schema:
|
|
63
|
-
code:
|
|
57
|
+
schema: z.object({
|
|
58
|
+
code: z.string().describe('The Python code to execute.'),
|
|
64
59
|
}),
|
|
65
60
|
}, 'exec');
|
|
66
|
-
const webSearchTool = createZhitalkTool(
|
|
61
|
+
const webSearchTool = createZhitalkTool(webSearchToolImpl, {
|
|
67
62
|
name: 'web_search',
|
|
68
63
|
description: 'Search the web using Tavily. Useful for finding current information, news, and facts.',
|
|
69
|
-
schema:
|
|
70
|
-
query:
|
|
64
|
+
schema: z.object({
|
|
65
|
+
query: z.string().describe('The search query.'),
|
|
71
66
|
}),
|
|
72
67
|
}, 'network');
|
|
73
|
-
const webFetchTool = createZhitalkTool(
|
|
68
|
+
const webFetchTool = createZhitalkTool(webFetchToolImpl, {
|
|
74
69
|
name: 'web_fetch',
|
|
75
70
|
description: 'Fetch the content of a web page by URL. Returns the raw HTML/text content. Useful when you need to read a specific page.',
|
|
76
|
-
schema:
|
|
77
|
-
url:
|
|
71
|
+
schema: z.object({
|
|
72
|
+
url: z.string().describe('The full URL of the web page to fetch.'),
|
|
78
73
|
}),
|
|
79
74
|
}, 'network');
|
|
80
|
-
const loadSkillTool = createZhitalkTool(
|
|
75
|
+
const loadSkillTool = createZhitalkTool(loadSkillToolImpl, {
|
|
81
76
|
name: 'load_skill',
|
|
82
77
|
description: 'Load the full content of a skill by its name. Call this when you need to use a specific skill to handle the user request. You can only load one skill at a time.',
|
|
83
|
-
schema:
|
|
84
|
-
name:
|
|
78
|
+
schema: z.object({
|
|
79
|
+
name: z.string().describe('The name of the skill to load.'),
|
|
85
80
|
}),
|
|
86
81
|
}, 'read');
|
|
87
|
-
const memoryCreateTool = createZhitalkTool(
|
|
82
|
+
const memoryCreateTool = createZhitalkTool(memoryCreateToolImpl, {
|
|
88
83
|
name: 'memory_create',
|
|
89
84
|
description: 'Save a piece of memory to the database. Use this when the user shares something worth remembering, such as a personal fact, event, preference, or skill.',
|
|
90
|
-
schema:
|
|
91
|
-
type:
|
|
85
|
+
schema: z.object({
|
|
86
|
+
type: z
|
|
92
87
|
.enum(['fact', 'event', 'preference', 'skill'])
|
|
93
88
|
.describe('The type of memory to save.'),
|
|
94
|
-
content:
|
|
89
|
+
content: z
|
|
95
90
|
.string()
|
|
96
91
|
.describe('The natural language description of the memory.'),
|
|
97
|
-
keywords:
|
|
98
|
-
.array(
|
|
92
|
+
keywords: z
|
|
93
|
+
.array(z.string())
|
|
99
94
|
.optional()
|
|
100
95
|
.describe('Optional keywords for retrieval, as an array of strings.'),
|
|
101
|
-
importance:
|
|
96
|
+
importance: z
|
|
102
97
|
.number()
|
|
103
98
|
.min(1)
|
|
104
99
|
.max(5)
|
|
@@ -106,14 +101,14 @@ const memoryCreateTool = createZhitalkTool(memory_create_tool_1.memoryCreateTool
|
|
|
106
101
|
.describe('Importance level from 1 to 5. Default is 3.'),
|
|
107
102
|
}),
|
|
108
103
|
}, 'db');
|
|
109
|
-
const memoryRetrieveTool = createZhitalkTool(
|
|
104
|
+
const memoryRetrieveTool = createZhitalkTool(memoryRetrieveToolImpl, {
|
|
110
105
|
name: 'memory_retrieve',
|
|
111
106
|
description: 'Retrieve relevant memories from the database using full-text search. Use this when the user asks about something that may have been remembered before but is not in the current conversation context. Extract a few key keywords from the question and pass them as the query.',
|
|
112
|
-
schema:
|
|
113
|
-
query:
|
|
114
|
-
.array(
|
|
107
|
+
schema: z.object({
|
|
108
|
+
query: z
|
|
109
|
+
.array(z.string())
|
|
115
110
|
.describe('Keywords to search for in memories.'),
|
|
116
|
-
limit:
|
|
111
|
+
limit: z
|
|
117
112
|
.number()
|
|
118
113
|
.min(1)
|
|
119
114
|
.max(50)
|
|
@@ -121,45 +116,45 @@ const memoryRetrieveTool = createZhitalkTool(memory_retrieve_tool_1.memoryRetrie
|
|
|
121
116
|
.describe('Maximum number of memories to return. Default is 10.'),
|
|
122
117
|
}),
|
|
123
118
|
}, 'db');
|
|
124
|
-
const memoryDeleteTool = createZhitalkTool(
|
|
119
|
+
const memoryDeleteTool = createZhitalkTool(memoryDeleteToolImpl, {
|
|
125
120
|
name: 'memory_delete',
|
|
126
121
|
description: 'Delete a memory from the database by its id. Use this when the user wants to forget or remove a specific memory.',
|
|
127
|
-
schema:
|
|
128
|
-
id:
|
|
122
|
+
schema: z.object({
|
|
123
|
+
id: z
|
|
129
124
|
.number()
|
|
130
125
|
.int()
|
|
131
126
|
.positive()
|
|
132
127
|
.describe('The id of the memory to delete.'),
|
|
133
128
|
}),
|
|
134
129
|
}, 'db');
|
|
135
|
-
const profileUpdateTool = createZhitalkTool(
|
|
130
|
+
const profileUpdateTool = createZhitalkTool(profileUpdateToolImpl, {
|
|
136
131
|
name: 'profile_update',
|
|
137
132
|
description: "Update the user's profile information. When providing new profile info, also include all other fields mentioned in <profile_info> — all profile information must be updated together.",
|
|
138
|
-
schema:
|
|
139
|
-
profile_info:
|
|
133
|
+
schema: z.object({
|
|
134
|
+
profile_info: z
|
|
140
135
|
.string()
|
|
141
136
|
.describe('The complete profile information in markdown format, including all existing and updated fields.'),
|
|
142
137
|
}),
|
|
143
138
|
}, 'write');
|
|
144
|
-
const agentTool = createZhitalkTool(
|
|
139
|
+
const agentTool = createZhitalkTool(agentToolImpl, {
|
|
145
140
|
name: 'agent_tool',
|
|
146
141
|
description: 'Launch a sub-agent to execute an independent task. The sub-agent has access to all tools (except this one), skills, memory, and hooks. It will run to completion and return its final result. Use this for tasks that can be delegated, such as research, code generation, or data processing.',
|
|
147
|
-
schema:
|
|
148
|
-
prompt:
|
|
142
|
+
schema: z.object({
|
|
143
|
+
prompt: z
|
|
149
144
|
.string()
|
|
150
145
|
.describe('A clear, self-contained task prompt for the sub-agent. It should include all necessary context because the sub-agent cannot see the current conversation history.'),
|
|
151
146
|
}),
|
|
152
147
|
}, 'exec');
|
|
153
|
-
async function maybePersistedOutput(content, toolCallId) {
|
|
148
|
+
export async function maybePersistedOutput(content, toolCallId) {
|
|
154
149
|
const MAX_LENGTH = 50000;
|
|
155
150
|
if (content.length <= MAX_LENGTH) {
|
|
156
151
|
return content;
|
|
157
152
|
}
|
|
158
153
|
const id = toolCallId || Math.random().toString(36).slice(2, 9);
|
|
159
|
-
const dir =
|
|
160
|
-
const filePath =
|
|
161
|
-
await
|
|
162
|
-
await
|
|
154
|
+
const dir = resolve(WORKSPACE_DIR, '.tool_output');
|
|
155
|
+
const filePath = resolve(dir, `tool_output_${id}.txt`);
|
|
156
|
+
await mkdir(dir, { recursive: true });
|
|
157
|
+
await writeFile(filePath, content, 'utf-8');
|
|
163
158
|
return `<persisted-output>
|
|
164
159
|
Output too large (${(content.length / 1024).toFixed(1)}KB).
|
|
165
160
|
Full output saved to: ${filePath}
|
|
@@ -171,7 +166,7 @@ ${content.slice(0, 2000)}
|
|
|
171
166
|
...
|
|
172
167
|
</persisted-output>`;
|
|
173
168
|
}
|
|
174
|
-
|
|
169
|
+
export const nativeTools = [
|
|
175
170
|
readFileTool,
|
|
176
171
|
writeFileTool,
|
|
177
172
|
execTool,
|
|
@@ -186,8 +181,8 @@ exports.nativeTools = [
|
|
|
186
181
|
profileUpdateTool,
|
|
187
182
|
agentTool,
|
|
188
183
|
];
|
|
189
|
-
|
|
190
|
-
async function initTools() {
|
|
191
|
-
const mcpTools = await
|
|
192
|
-
|
|
184
|
+
export let tools = [...nativeTools];
|
|
185
|
+
export async function initTools() {
|
|
186
|
+
const mcpTools = await initMcpTools();
|
|
187
|
+
tools = [...nativeTools, ...mcpTools];
|
|
193
188
|
}
|
package/dist/agent/utils.d.ts
CHANGED
package/dist/agent/utils.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { resolve, join } from 'path';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
export function resolvePath(filepath) {
|
|
4
|
+
if (filepath.startsWith('~/')) {
|
|
5
|
+
filepath = join(homedir(), filepath.slice(2));
|
|
6
|
+
}
|
|
7
|
+
else if (filepath === '~') {
|
|
8
|
+
filepath = homedir();
|
|
9
|
+
}
|
|
10
|
+
return resolve(filepath);
|
|
11
|
+
}
|
|
12
|
+
export function formatRelativeTime(ts) {
|
|
6
13
|
const diffMs = Date.now() - new Date(ts).getTime();
|
|
7
14
|
const diffMin = Math.floor(diffMs / 60000);
|
|
8
15
|
const diffHour = Math.floor(diffMin / 60);
|
|
@@ -23,7 +30,7 @@ function formatRelativeTime(ts) {
|
|
|
23
30
|
return '1天前';
|
|
24
31
|
return `${diffDay}天前`;
|
|
25
32
|
}
|
|
26
|
-
function truncate(str, maxLen) {
|
|
33
|
+
export function truncate(str, maxLen) {
|
|
27
34
|
if (!str)
|
|
28
35
|
return '-';
|
|
29
36
|
return str.length > maxLen ? str.slice(0, maxLen) + '...' : str;
|
package/dist/index.js
CHANGED
|
@@ -1,62 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Object.defineProperty(o, k2, desc);
|
|
10
|
-
}) : (function(o, m, k, k2) {
|
|
11
|
-
if (k2 === undefined) k2 = k;
|
|
12
|
-
o[k2] = m[k];
|
|
13
|
-
}));
|
|
14
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
-
}) : function(o, v) {
|
|
17
|
-
o["default"] = v;
|
|
18
|
-
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
-
var ownKeys = function(o) {
|
|
21
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
-
var ar = [];
|
|
23
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
-
return ar;
|
|
25
|
-
};
|
|
26
|
-
return ownKeys(o);
|
|
27
|
-
};
|
|
28
|
-
return function (mod) {
|
|
29
|
-
if (mod && mod.__esModule) return mod;
|
|
30
|
-
var result = {};
|
|
31
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
-
__setModuleDefault(result, mod);
|
|
33
|
-
return result;
|
|
34
|
-
};
|
|
35
|
-
})();
|
|
36
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
const commander_1 = require("commander");
|
|
38
|
-
const fs_1 = require("fs");
|
|
39
|
-
const path_1 = require("path");
|
|
40
|
-
const config_1 = require("./agent/config");
|
|
41
|
-
const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../package.json'), 'utf-8'));
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { readFileSync, existsSync } from 'fs';
|
|
4
|
+
import { join, dirname } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { CONFIG_PATH } from './agent/config.js';
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
|
|
42
9
|
async function main() {
|
|
43
|
-
const program = new
|
|
10
|
+
const program = new Command();
|
|
44
11
|
program.name(pkg.name).description(pkg.description).version(pkg.version);
|
|
12
|
+
program
|
|
13
|
+
.command('config')
|
|
14
|
+
.description('Print the configuration file path')
|
|
15
|
+
.action(() => {
|
|
16
|
+
console.log(`配置文件位置: ${CONFIG_PATH}`);
|
|
17
|
+
console.log('请使用编辑器打开并修改配置,修改完成后重启 zhitalk');
|
|
18
|
+
});
|
|
45
19
|
if (process.argv.length > 2) {
|
|
46
20
|
program.parse();
|
|
47
21
|
return;
|
|
48
22
|
}
|
|
49
|
-
if (!
|
|
50
|
-
const { runInstall } = await
|
|
23
|
+
if (!existsSync(CONFIG_PATH)) {
|
|
24
|
+
const { runInstall } = await import('./install.js');
|
|
51
25
|
await runInstall();
|
|
52
26
|
return;
|
|
53
27
|
}
|
|
54
|
-
const { initColors } = await
|
|
55
|
-
const { initDb } = await
|
|
56
|
-
const { initAgent } = await
|
|
57
|
-
const { interactiveChat } = await
|
|
58
|
-
const { shutdownMcp } = await
|
|
59
|
-
const { checkModel } = await
|
|
28
|
+
const { initColors } = await import('./agent/colors.js');
|
|
29
|
+
const { initDb } = await import('./agent/db.js');
|
|
30
|
+
const { initAgent } = await import('./agent/agent.js');
|
|
31
|
+
const { interactiveChat } = await import('./agent/cli.js');
|
|
32
|
+
const { shutdownMcp } = await import('./agent/mcp/index.js');
|
|
33
|
+
const { checkModel } = await import('./agent/model.js');
|
|
60
34
|
await initColors();
|
|
61
35
|
await checkModel();
|
|
62
36
|
initDb();
|