zhitalk 0.0.0 → 0.0.2

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.
Files changed (83) hide show
  1. package/CLAUDE.md +98 -0
  2. package/README.md +18 -1
  3. package/dist/agent/agent.d.ts +24 -0
  4. package/dist/agent/agent.js +345 -0
  5. package/dist/agent/cli.d.ts +1 -0
  6. package/dist/agent/cli.js +185 -0
  7. package/dist/agent/colors.d.ts +19 -0
  8. package/dist/agent/colors.js +81 -0
  9. package/dist/agent/commands.d.ts +7 -0
  10. package/dist/agent/commands.js +69 -0
  11. package/dist/agent/config.d.ts +38 -0
  12. package/dist/agent/config.js +116 -0
  13. package/dist/agent/context.d.ts +3 -0
  14. package/dist/agent/context.js +107 -0
  15. package/dist/agent/db.d.ts +21 -0
  16. package/dist/agent/db.js +159 -0
  17. package/dist/agent/hooks.d.ts +27 -0
  18. package/dist/agent/hooks.js +115 -0
  19. package/dist/agent/mcp/client.d.ts +25 -0
  20. package/dist/agent/mcp/client.js +113 -0
  21. package/dist/agent/mcp/index.d.ts +4 -0
  22. package/dist/agent/mcp/index.js +27 -0
  23. package/dist/agent/mcp/wrapper.d.ts +7 -0
  24. package/dist/agent/mcp/wrapper.js +25 -0
  25. package/dist/agent/model.d.ts +5 -0
  26. package/dist/agent/model.js +31 -0
  27. package/dist/agent/permission/dangerous-path.json +115 -0
  28. package/dist/agent/permission/exec.d.ts +11 -0
  29. package/dist/agent/permission/exec.js +34 -0
  30. package/dist/agent/permission/is-dangerous-path.d.ts +1 -0
  31. package/dist/agent/permission/is-dangerous-path.js +53 -0
  32. package/dist/agent/permission/is-safe-domains.d.ts +1 -0
  33. package/dist/agent/permission/is-safe-domains.js +142 -0
  34. package/dist/agent/permission/network.d.ts +8 -0
  35. package/dist/agent/permission/network.js +14 -0
  36. package/dist/agent/permission/read.d.ts +9 -0
  37. package/dist/agent/permission/read.js +17 -0
  38. package/dist/agent/permission/util.d.ts +11 -0
  39. package/dist/agent/permission/util.js +160 -0
  40. package/dist/agent/permission/write.d.ts +11 -0
  41. package/dist/agent/permission/write.js +21 -0
  42. package/dist/agent/prompt.d.ts +1 -0
  43. package/dist/agent/prompt.js +50 -0
  44. package/dist/agent/skills.d.ts +8 -0
  45. package/dist/agent/skills.js +91 -0
  46. package/dist/agent/tools/agent_tool.d.ts +3 -0
  47. package/dist/agent/tools/agent_tool.js +44 -0
  48. package/dist/agent/tools/exec_tool.d.ts +3 -0
  49. package/dist/agent/tools/exec_tool.js +28 -0
  50. package/dist/agent/tools/load_skill_tool.d.ts +3 -0
  51. package/dist/agent/tools/load_skill_tool.js +15 -0
  52. package/dist/agent/tools/memory_create_tool.d.ts +6 -0
  53. package/dist/agent/tools/memory_create_tool.js +37 -0
  54. package/dist/agent/tools/memory_delete_tool.d.ts +3 -0
  55. package/dist/agent/tools/memory_delete_tool.js +28 -0
  56. package/dist/agent/tools/memory_retrieve_tool.d.ts +4 -0
  57. package/dist/agent/tools/memory_retrieve_tool.js +24 -0
  58. package/dist/agent/tools/profile_update_tool.d.ts +3 -0
  59. package/dist/agent/tools/profile_update_tool.js +50 -0
  60. package/dist/agent/tools/read_file_tool.d.ts +3 -0
  61. package/dist/agent/tools/read_file_tool.js +16 -0
  62. package/dist/agent/tools/run_js_tool.d.ts +3 -0
  63. package/dist/agent/tools/run_js_tool.js +36 -0
  64. package/dist/agent/tools/run_py_tool.d.ts +3 -0
  65. package/dist/agent/tools/run_py_tool.js +27 -0
  66. package/dist/agent/tools/search.d.ts +3 -0
  67. package/dist/agent/tools/search.js +10 -0
  68. package/dist/agent/tools/web_fetch_tool.d.ts +3 -0
  69. package/dist/agent/tools/web_fetch_tool.js +33 -0
  70. package/dist/agent/tools/web_search_tool.d.ts +3 -0
  71. package/dist/agent/tools/web_search_tool.js +38 -0
  72. package/dist/agent/tools/write_file_tool.d.ts +4 -0
  73. package/dist/agent/tools/write_file_tool.js +15 -0
  74. package/dist/agent/tools.d.ts +8 -0
  75. package/dist/agent/tools.js +193 -0
  76. package/dist/agent/utils.d.ts +2 -0
  77. package/dist/agent/utils.js +30 -0
  78. package/dist/index.d.ts +2 -0
  79. package/dist/index.js +72 -0
  80. package/dist/install.d.ts +1 -0
  81. package/dist/install.js +108 -0
  82. package/package.json +43 -6
  83. package/index.js +0 -1
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.memoryCreateTool = memoryCreateTool;
7
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
8
+ const db_1 = require("../db");
9
+ const VALID_TYPES = ['fact', 'event', 'preference', 'skill'];
10
+ async function memoryCreateTool({ type, content, keywords, importance, }, config) {
11
+ if (!VALID_TYPES.includes(type)) {
12
+ return `Error: type must be one of ${VALID_TYPES.join(', ')}.`;
13
+ }
14
+ const trimmed = content?.trim();
15
+ if (!trimmed) {
16
+ return 'Error: content is required.';
17
+ }
18
+ const importanceValue = importance ?? 3;
19
+ if (importanceValue < 1 || importanceValue > 5) {
20
+ return 'Error: importance must be between 1 and 5.';
21
+ }
22
+ const sessionId = config?.configurable?.thread_id ?? 'default-session';
23
+ const keywordsJson = keywords && keywords.length > 0 ? JSON.stringify(keywords) : null;
24
+ const db = new better_sqlite3_1.default(db_1.DB_PATH);
25
+ try {
26
+ const stmt = db.prepare(`INSERT INTO memory (type, content, keywords, importance, session_id)
27
+ VALUES (?, ?, ?, ?, ?)`);
28
+ stmt.run(type, trimmed, keywordsJson, importanceValue, sessionId);
29
+ return 'Memory saved successfully.';
30
+ }
31
+ catch (err) {
32
+ return `Error: ${err.message}`;
33
+ }
34
+ finally {
35
+ db.close();
36
+ }
37
+ }
@@ -0,0 +1,3 @@
1
+ export declare function memoryDeleteTool({ id, }: {
2
+ id: number;
3
+ }, _config?: any): Promise<string>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.memoryDeleteTool = memoryDeleteTool;
7
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
8
+ const db_1 = require("../db");
9
+ async function memoryDeleteTool({ id, }, _config) {
10
+ if (!Number.isFinite(id) || id <= 0) {
11
+ return 'Error: id must be a positive integer.';
12
+ }
13
+ const db = new better_sqlite3_1.default(db_1.DB_PATH);
14
+ try {
15
+ const existing = db.prepare('SELECT 1 FROM memory WHERE id = ?').get(id);
16
+ if (!existing) {
17
+ return `Error: no memory found with id ${id}.`;
18
+ }
19
+ db.prepare('DELETE FROM memory WHERE id = ?').run(id);
20
+ return `Memory ${id} deleted successfully.`;
21
+ }
22
+ catch (err) {
23
+ return `Error: ${err.message}`;
24
+ }
25
+ finally {
26
+ db.close();
27
+ }
28
+ }
@@ -0,0 +1,4 @@
1
+ export declare function memoryRetrieveTool({ query, limit, }: {
2
+ query: string[];
3
+ limit?: number;
4
+ }, config?: any): Promise<string>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.memoryRetrieveTool = memoryRetrieveTool;
4
+ const db_1 = require("../db");
5
+ async function memoryRetrieveTool({ query, limit, }, config) {
6
+ const trimmedQueries = query?.map((q) => q.trim()).filter((q) => q.length > 0);
7
+ if (!trimmedQueries || trimmedQueries.length === 0) {
8
+ return 'Error: query is required.';
9
+ }
10
+ const limitValue = limit ?? 10;
11
+ if (limitValue < 1 || limitValue > 50) {
12
+ return 'Error: limit must be between 1 and 50.';
13
+ }
14
+ try {
15
+ const results = (0, db_1.searchMemories)(trimmedQueries, limitValue);
16
+ if (results.length === 0) {
17
+ return 'No relevant memories found.';
18
+ }
19
+ return JSON.stringify(results);
20
+ }
21
+ catch (err) {
22
+ return `Error: ${err.message}`;
23
+ }
24
+ }
@@ -0,0 +1,3 @@
1
+ export declare function profileUpdateTool({ profile_info, }: {
2
+ profile_info: string;
3
+ }): Promise<string>;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.profileUpdateTool = profileUpdateTool;
4
+ const promises_1 = require("fs/promises");
5
+ const path_1 = require("path");
6
+ const config_1 = require("../config");
7
+ function getProfilePaths() {
8
+ const dir = (0, path_1.resolve)(config_1.WORKSPACE_DIR, '.data');
9
+ return { dir, path: (0, path_1.resolve)(dir, 'profile.md') };
10
+ }
11
+ function generateBackupFilename() {
12
+ const dt = Date.now();
13
+ const random = Math.random().toString(36).slice(2, 8);
14
+ return `profile.${dt}-${random}.md`;
15
+ }
16
+ async function profileUpdateTool({ profile_info, }) {
17
+ if (!profile_info || profile_info.trim().length === 0) {
18
+ return 'Error: profile_info is empty.';
19
+ }
20
+ const { dir: profileDir, path: profilePath } = getProfilePaths();
21
+ try {
22
+ let existingContent = '';
23
+ let fileExists = false;
24
+ try {
25
+ existingContent = await (0, promises_1.readFile)(profilePath, 'utf-8');
26
+ fileExists = true;
27
+ }
28
+ catch (err) {
29
+ if (err.code !== 'ENOENT') {
30
+ return `Error reading existing profile: ${err.message}`;
31
+ }
32
+ }
33
+ const normalizedNew = profile_info.trim();
34
+ const normalizedExisting = existingContent.trim();
35
+ if (fileExists && normalizedNew === normalizedExisting) {
36
+ return 'Profile is already up to date. No changes made.';
37
+ }
38
+ await (0, promises_1.mkdir)(profileDir, { recursive: true });
39
+ if (fileExists) {
40
+ const backupFilename = generateBackupFilename();
41
+ const backupPath = (0, path_1.resolve)(profileDir, backupFilename);
42
+ await (0, promises_1.copyFile)(profilePath, backupPath);
43
+ }
44
+ await (0, promises_1.writeFile)(profilePath, profile_info, 'utf-8');
45
+ return `Profile updated successfully. File: ${profilePath}${fileExists ? ' (backup created)' : ''}`;
46
+ }
47
+ catch (err) {
48
+ return `Error: ${err.message}`;
49
+ }
50
+ }
@@ -0,0 +1,3 @@
1
+ export declare function readFileTool({ filepath }: {
2
+ filepath: string;
3
+ }): Promise<string>;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readFileTool = readFileTool;
4
+ const promises_1 = require("fs/promises");
5
+ async function readFileTool({ filepath }) {
6
+ try {
7
+ const content = await (0, promises_1.readFile)(filepath, 'utf-8');
8
+ return content;
9
+ }
10
+ catch (err) {
11
+ if (err.code === 'ENOENT') {
12
+ return 'Error: file not found.';
13
+ }
14
+ return `Error: ${err.message}`;
15
+ }
16
+ }
@@ -0,0 +1,3 @@
1
+ export declare function runJsTool({ code }: {
2
+ code: string;
3
+ }): Promise<string>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runJsTool = runJsTool;
4
+ const child_process_1 = require("child_process");
5
+ async function runJsTool({ code }) {
6
+ if (!code.trim()) {
7
+ return 'Error: code is empty.';
8
+ }
9
+ return new Promise((resolve) => {
10
+ const child = (0, child_process_1.spawn)('node', ['--input-type=module'], {
11
+ env: { ...process.env, NO_COLOR: '1', FORCE_COLOR: '0' },
12
+ });
13
+ let stdout = '';
14
+ let stderr = '';
15
+ child.stdout.on('data', (chunk) => {
16
+ stdout += chunk;
17
+ });
18
+ child.stderr.on('data', (chunk) => {
19
+ stderr += chunk;
20
+ });
21
+ child.on('close', (code) => {
22
+ if (code !== 0) {
23
+ resolve(`Error: ${stderr.trim() || 'unknown error'}`);
24
+ }
25
+ else {
26
+ const output = stdout || stderr;
27
+ resolve(output.trim() ? output : 'Code executed successfully with no output.');
28
+ }
29
+ });
30
+ child.on('error', (err) => {
31
+ resolve(`Error: ${err.message}`);
32
+ });
33
+ child.stdin.write(code);
34
+ child.stdin.end();
35
+ });
36
+ }
@@ -0,0 +1,3 @@
1
+ export declare function runPyTool({ code }: {
2
+ code: string;
3
+ }): Promise<string>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runPyTool = runPyTool;
4
+ const child_process_1 = require("child_process");
5
+ const util_1 = require("util");
6
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
7
+ async function runPyTool({ code }) {
8
+ const trimmed = code.trim();
9
+ if (!trimmed) {
10
+ return 'Error: code is empty.';
11
+ }
12
+ try {
13
+ await execAsync('python3 --version', { timeout: 5000 });
14
+ }
15
+ catch {
16
+ return 'Error: Python3 is not installed on this system. Please install Python3 to execute Python code.';
17
+ }
18
+ const base64Code = Buffer.from(trimmed).toString('base64');
19
+ const command = `python3 -c "import base64; exec(base64.b64decode('${base64Code}').decode('utf-8'))"`;
20
+ try {
21
+ const { stdout, stderr } = await execAsync(command, { cwd: process.cwd(), timeout: 30000 });
22
+ return stdout || stderr || 'Code executed successfully with no output.';
23
+ }
24
+ catch (err) {
25
+ return `Error: ${err.message}`;
26
+ }
27
+ }
@@ -0,0 +1,3 @@
1
+ export declare function search({ query }: {
2
+ query: string;
3
+ }): Promise<string>;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.search = search;
4
+ async function search({ query }) {
5
+ if (query.toLowerCase().includes('sf') ||
6
+ query.toLowerCase().includes('san francisco')) {
7
+ return "It's 60 degrees and foggy.";
8
+ }
9
+ return "It's 90 degrees and sunny.";
10
+ }
@@ -0,0 +1,3 @@
1
+ export declare function webFetchTool({ url }: {
2
+ url: string;
3
+ }): Promise<string>;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.webFetchTool = webFetchTool;
4
+ const MAX_LENGTH = 8000;
5
+ async function webFetchTool({ url }) {
6
+ const trimmed = url.trim();
7
+ if (!trimmed) {
8
+ return 'Error: url is empty.';
9
+ }
10
+ try {
11
+ const response = await fetch(trimmed, {
12
+ headers: {
13
+ 'User-Agent': 'Mozilla/5.0 (compatible; ZhitalkBot/1.0)',
14
+ },
15
+ signal: AbortSignal.timeout(10000),
16
+ });
17
+ if (!response.ok) {
18
+ return `Error: HTTP ${response.status} ${response.statusText}`;
19
+ }
20
+ const text = await response.text();
21
+ if (text.length > MAX_LENGTH) {
22
+ return text.slice(0, MAX_LENGTH) + '\n\n[Content truncated due to length]';
23
+ }
24
+ return text;
25
+ }
26
+ catch (err) {
27
+ const error = err;
28
+ if (error.name === 'AbortError' || error.name === 'TimeoutError') {
29
+ return 'Error: Request timed out after 10 seconds.';
30
+ }
31
+ return `Error: ${error.message}`;
32
+ }
33
+ }
@@ -0,0 +1,3 @@
1
+ export declare function webSearchTool({ query }: {
2
+ query: string;
3
+ }): Promise<string>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.webSearchTool = webSearchTool;
4
+ const tavily_1 = require("@langchain/tavily");
5
+ const config_1 = require("../config");
6
+ async function webSearchTool({ query }) {
7
+ const tavilyApiKey = (0, config_1.getEnv)('TAVILY_API_KEY');
8
+ if (!tavilyApiKey) {
9
+ return 'Error: 未配置 TAVILY_API_KEY。请在 ~/.zhitalk/zhitalk.json 的 env 中设置 TAVILY_API_KEY。';
10
+ }
11
+ const tavilySearch = new tavily_1.TavilySearch({
12
+ maxResults: 3,
13
+ topic: 'general',
14
+ tavilyApiKey,
15
+ });
16
+ try {
17
+ const result = await tavilySearch.invoke({ query });
18
+ if ('error' in result && result.error) {
19
+ return `Error: ${result.error}`;
20
+ }
21
+ const lines = [];
22
+ lines.push(`Query: ${result.query}`);
23
+ if (result.answer) {
24
+ lines.push(`Answer: ${result.answer}`);
25
+ }
26
+ lines.push('');
27
+ lines.push('Results:');
28
+ for (let i = 0; i < result.results.length; i++) {
29
+ const r = result.results[i];
30
+ lines.push(`${i + 1}. ${r.title} (${r.url})`);
31
+ lines.push(` ${r.content}`);
32
+ }
33
+ return lines.join('\n');
34
+ }
35
+ catch (err) {
36
+ return `Error: ${err.message}`;
37
+ }
38
+ }
@@ -0,0 +1,4 @@
1
+ export declare function writeFileTool({ filepath, content }: {
2
+ filepath: string;
3
+ content: string;
4
+ }): Promise<string>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.writeFileTool = writeFileTool;
4
+ const promises_1 = require("fs/promises");
5
+ const path_1 = require("path");
6
+ async function writeFileTool({ filepath, content }) {
7
+ try {
8
+ await (0, promises_1.mkdir)((0, path_1.dirname)(filepath), { recursive: true });
9
+ await (0, promises_1.writeFile)(filepath, content, 'utf-8');
10
+ return `File "${filepath}" written successfully.`;
11
+ }
12
+ catch (err) {
13
+ return `Error: ${err.message}`;
14
+ }
15
+ }
@@ -0,0 +1,8 @@
1
+ import { DynamicStructuredTool } from '@langchain/core/tools';
2
+ export type ZhitalkTool = DynamicStructuredTool & {
3
+ permission_level: string;
4
+ };
5
+ export declare function maybePersistedOutput(content: string, toolCallId: string): Promise<string>;
6
+ export declare const nativeTools: ZhitalkTool[];
7
+ export declare let tools: ZhitalkTool[];
8
+ export declare function initTools(): Promise<void>;
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tools = exports.nativeTools = void 0;
4
+ exports.maybePersistedOutput = maybePersistedOutput;
5
+ exports.initTools = initTools;
6
+ const tools_1 = require("@langchain/core/tools");
7
+ const zod_1 = require("zod");
8
+ const promises_1 = require("fs/promises");
9
+ const path_1 = require("path");
10
+ const config_1 = require("./config");
11
+ const read_file_tool_1 = require("./tools/read_file_tool");
12
+ const write_file_tool_1 = require("./tools/write_file_tool");
13
+ const exec_tool_1 = require("./tools/exec_tool");
14
+ const run_js_tool_1 = require("./tools/run_js_tool");
15
+ const run_py_tool_1 = require("./tools/run_py_tool");
16
+ const web_search_tool_1 = require("./tools/web_search_tool");
17
+ const web_fetch_tool_1 = require("./tools/web_fetch_tool");
18
+ const load_skill_tool_1 = require("./tools/load_skill_tool");
19
+ const memory_create_tool_1 = require("./tools/memory_create_tool");
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");
25
+ function createZhitalkTool(impl, options, permission_level) {
26
+ const t = (0, tools_1.tool)(impl, options);
27
+ t.permission_level = permission_level;
28
+ return t;
29
+ }
30
+ const readFileTool = createZhitalkTool(read_file_tool_1.readFileTool, {
31
+ name: 'read_file',
32
+ description: 'Read the contents of a file.',
33
+ schema: zod_1.z.object({
34
+ filepath: zod_1.z.string().describe('The path of the file to read. Can be relative, absolute, or start with ~.'),
35
+ }),
36
+ }, 'read');
37
+ const writeFileTool = createZhitalkTool(write_file_tool_1.writeFileTool, {
38
+ name: 'write_file',
39
+ description: 'Create or overwrite a file. Will create parent directories if needed.',
40
+ schema: zod_1.z.object({
41
+ filepath: zod_1.z.string().describe('The path of the file to write. Can be relative, absolute, or start with ~.'),
42
+ content: zod_1.z.string().describe('The content to write to the file.'),
43
+ }),
44
+ }, 'write');
45
+ const execTool = createZhitalkTool(exec_tool_1.execTool, {
46
+ name: 'exec',
47
+ 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: zod_1.z.object({
49
+ command: zod_1.z.string().describe('The shell command to execute.'),
50
+ }),
51
+ }, 'exec');
52
+ const runJsTool = createZhitalkTool(run_js_tool_1.runJsTool, {
53
+ name: 'run_js',
54
+ description: 'Execute JavaScript code using Node.js in the current directory. Returns stdout/stderr or error messages.',
55
+ schema: zod_1.z.object({
56
+ code: zod_1.z.string().describe('The JavaScript code to execute.'),
57
+ }),
58
+ }, 'exec');
59
+ const runPyTool = createZhitalkTool(run_py_tool_1.runPyTool, {
60
+ name: 'run_py',
61
+ description: 'Execute Python code using Python3 in the current directory. Returns stdout/stderr or error messages.',
62
+ schema: zod_1.z.object({
63
+ code: zod_1.z.string().describe('The Python code to execute.'),
64
+ }),
65
+ }, 'exec');
66
+ const webSearchTool = createZhitalkTool(web_search_tool_1.webSearchTool, {
67
+ name: 'web_search',
68
+ description: 'Search the web using Tavily. Useful for finding current information, news, and facts.',
69
+ schema: zod_1.z.object({
70
+ query: zod_1.z.string().describe('The search query.'),
71
+ }),
72
+ }, 'network');
73
+ const webFetchTool = createZhitalkTool(web_fetch_tool_1.webFetchTool, {
74
+ name: 'web_fetch',
75
+ 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: zod_1.z.object({
77
+ url: zod_1.z.string().describe('The full URL of the web page to fetch.'),
78
+ }),
79
+ }, 'network');
80
+ const loadSkillTool = createZhitalkTool(load_skill_tool_1.loadSkillTool, {
81
+ name: 'load_skill',
82
+ 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: zod_1.z.object({
84
+ name: zod_1.z.string().describe('The name of the skill to load.'),
85
+ }),
86
+ }, 'read');
87
+ const memoryCreateTool = createZhitalkTool(memory_create_tool_1.memoryCreateTool, {
88
+ name: 'memory_create',
89
+ 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: zod_1.z.object({
91
+ type: zod_1.z
92
+ .enum(['fact', 'event', 'preference', 'skill'])
93
+ .describe('The type of memory to save.'),
94
+ content: zod_1.z
95
+ .string()
96
+ .describe('The natural language description of the memory.'),
97
+ keywords: zod_1.z
98
+ .array(zod_1.z.string())
99
+ .optional()
100
+ .describe('Optional keywords for retrieval, as an array of strings.'),
101
+ importance: zod_1.z
102
+ .number()
103
+ .min(1)
104
+ .max(5)
105
+ .optional()
106
+ .describe('Importance level from 1 to 5. Default is 3.'),
107
+ }),
108
+ }, 'db');
109
+ const memoryRetrieveTool = createZhitalkTool(memory_retrieve_tool_1.memoryRetrieveTool, {
110
+ name: 'memory_retrieve',
111
+ 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: zod_1.z.object({
113
+ query: zod_1.z
114
+ .array(zod_1.z.string())
115
+ .describe('Keywords to search for in memories.'),
116
+ limit: zod_1.z
117
+ .number()
118
+ .min(1)
119
+ .max(50)
120
+ .optional()
121
+ .describe('Maximum number of memories to return. Default is 10.'),
122
+ }),
123
+ }, 'db');
124
+ const memoryDeleteTool = createZhitalkTool(memory_delete_tool_1.memoryDeleteTool, {
125
+ name: 'memory_delete',
126
+ 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: zod_1.z.object({
128
+ id: zod_1.z
129
+ .number()
130
+ .int()
131
+ .positive()
132
+ .describe('The id of the memory to delete.'),
133
+ }),
134
+ }, 'db');
135
+ const profileUpdateTool = createZhitalkTool(profile_update_tool_1.profileUpdateTool, {
136
+ name: 'profile_update',
137
+ 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: zod_1.z.object({
139
+ profile_info: zod_1.z
140
+ .string()
141
+ .describe('The complete profile information in markdown format, including all existing and updated fields.'),
142
+ }),
143
+ }, 'write');
144
+ const agentTool = createZhitalkTool(agent_tool_1.agentTool, {
145
+ name: 'agent_tool',
146
+ 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: zod_1.z.object({
148
+ prompt: zod_1.z
149
+ .string()
150
+ .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
+ }),
152
+ }, 'exec');
153
+ async function maybePersistedOutput(content, toolCallId) {
154
+ const MAX_LENGTH = 50000;
155
+ if (content.length <= MAX_LENGTH) {
156
+ return content;
157
+ }
158
+ const id = toolCallId || Math.random().toString(36).slice(2, 9);
159
+ const dir = (0, path_1.resolve)(config_1.WORKSPACE_DIR, '.tool_output');
160
+ const filePath = (0, path_1.resolve)(dir, `tool_output_${id}.txt`);
161
+ await (0, promises_1.mkdir)(dir, { recursive: true });
162
+ await (0, promises_1.writeFile)(filePath, content, 'utf-8');
163
+ return `<persisted-output>
164
+ Output too large (${(content.length / 1024).toFixed(1)}KB).
165
+ Full output saved to: ${filePath}
166
+
167
+ If you need the complete content, it is recommended to read it in segments.
168
+
169
+ Preview (first 2KB):
170
+ ${content.slice(0, 2000)}
171
+ ...
172
+ </persisted-output>`;
173
+ }
174
+ exports.nativeTools = [
175
+ readFileTool,
176
+ writeFileTool,
177
+ execTool,
178
+ runJsTool,
179
+ runPyTool,
180
+ webSearchTool,
181
+ webFetchTool,
182
+ loadSkillTool,
183
+ memoryCreateTool,
184
+ memoryRetrieveTool,
185
+ memoryDeleteTool,
186
+ profileUpdateTool,
187
+ agentTool,
188
+ ];
189
+ exports.tools = [...exports.nativeTools];
190
+ async function initTools() {
191
+ const mcpTools = await (0, mcp_1.initMcpTools)();
192
+ exports.tools = [...exports.nativeTools, ...mcpTools];
193
+ }
@@ -0,0 +1,2 @@
1
+ export declare function formatRelativeTime(ts: string): string;
2
+ export declare function truncate(str: string | null, maxLen: number): string;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatRelativeTime = formatRelativeTime;
4
+ exports.truncate = truncate;
5
+ function formatRelativeTime(ts) {
6
+ const diffMs = Date.now() - new Date(ts).getTime();
7
+ const diffMin = Math.floor(diffMs / 60000);
8
+ const diffHour = Math.floor(diffMin / 60);
9
+ const diffDay = Math.floor(diffHour / 24);
10
+ if (diffMin < 1)
11
+ return '刚刚';
12
+ if (diffMin < 5)
13
+ return '5分钟内';
14
+ if (diffMin < 10)
15
+ return '10分钟内';
16
+ if (diffMin < 30)
17
+ return '30分钟内';
18
+ if (diffMin < 60)
19
+ return '1小时内';
20
+ if (diffHour < 24)
21
+ return `${diffHour}小时内`;
22
+ if (diffDay < 2)
23
+ return '1天前';
24
+ return `${diffDay}天前`;
25
+ }
26
+ function truncate(str, maxLen) {
27
+ if (!str)
28
+ return '-';
29
+ return str.length > maxLen ? str.slice(0, maxLen) + '...' : str;
30
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};