zhitalk 0.0.0 → 0.0.3

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 +36 -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,159 @@
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.DB_PATH = void 0;
7
+ exports.searchMemories = searchMemories;
8
+ exports.threadIdExists = threadIdExists;
9
+ exports.initDb = initDb;
10
+ exports.listRecentSessions = listRecentSessions;
11
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
12
+ const fs_1 = require("fs");
13
+ const path_1 = require("path");
14
+ const config_1 = require("./config");
15
+ const utils_1 = require("./utils");
16
+ exports.DB_PATH = (0, path_1.join)(config_1.WORKSPACE_DIR, '.data', 'checkpointer.db');
17
+ (0, fs_1.mkdirSync)((0, path_1.dirname)(exports.DB_PATH), { recursive: true });
18
+ function searchMemories(query, limit = 10) {
19
+ const trimmedQueries = query.map((q) => q.trim()).filter((q) => q.length > 0);
20
+ if (trimmedQueries.length === 0) {
21
+ return [];
22
+ }
23
+ const queryStr = trimmedQueries.join(' OR ').replace(/-/g, ' ');
24
+ const db = new better_sqlite3_1.default(exports.DB_PATH);
25
+ try {
26
+ const rows = db.prepare(`
27
+ WITH ranked AS (
28
+ SELECT
29
+ m.*,
30
+ -bm25(memory_fts, 10.0, 5.0) AS relevance_score,
31
+ (m.importance * 0.3) AS importance_score,
32
+ (
33
+ 1.0 / (
34
+ 1.0 +
35
+ ((strftime('%s','now') - strftime('%s', m.updated_at)) / 86400.0)
36
+ )
37
+ ) AS time_score
38
+ FROM memory_fts
39
+ JOIN memory m ON m.id = memory_fts.rowid
40
+ WHERE memory_fts MATCH ?
41
+ )
42
+ SELECT *,
43
+ (
44
+ relevance_score * 0.6 +
45
+ importance_score * 0.3 +
46
+ time_score * 0.1
47
+ ) AS final_score
48
+ FROM ranked
49
+ ORDER BY final_score DESC
50
+ LIMIT ?
51
+ `).all(queryStr, limit);
52
+ return rows.map((r) => ({
53
+ id: r.id,
54
+ type: r.type,
55
+ content: r.content,
56
+ keywords: r.keywords,
57
+ importance: r.importance,
58
+ session_id: r.session_id,
59
+ created_at: r.created_at,
60
+ updated_at: r.updated_at,
61
+ final_score: r.final_score,
62
+ }));
63
+ }
64
+ finally {
65
+ db.close();
66
+ }
67
+ }
68
+ function threadIdExists(threadId) {
69
+ const db = new better_sqlite3_1.default(exports.DB_PATH);
70
+ try {
71
+ const row = db.prepare(`
72
+ SELECT 1 FROM checkpoints WHERE thread_id = ? LIMIT 1
73
+ `).get(threadId);
74
+ return !!row;
75
+ }
76
+ finally {
77
+ db.close();
78
+ }
79
+ }
80
+ function initDb() {
81
+ const db = new better_sqlite3_1.default(exports.DB_PATH);
82
+ try {
83
+ db.exec(`
84
+ CREATE TABLE IF NOT EXISTS memory (
85
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
86
+ type TEXT NOT NULL,
87
+ content TEXT NOT NULL,
88
+ keywords TEXT,
89
+ importance INTEGER DEFAULT 3,
90
+ session_id TEXT,
91
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
92
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
93
+ )
94
+ `);
95
+ db.exec(`
96
+ CREATE VIRTUAL TABLE IF NOT EXISTS memory_fts USING fts5(
97
+ content,
98
+ keywords,
99
+ content='memory', content_rowid='id'
100
+ )
101
+ `);
102
+ db.exec(`
103
+ CREATE TRIGGER IF NOT EXISTS memory_fts_insert AFTER INSERT ON memory BEGIN
104
+ INSERT INTO memory_fts(rowid, content, keywords)
105
+ VALUES (new.id, new.content, new.keywords);
106
+ END;
107
+
108
+ CREATE TRIGGER IF NOT EXISTS memory_fts_delete AFTER DELETE ON memory BEGIN
109
+ INSERT INTO memory_fts(memory_fts, rowid, content, keywords)
110
+ VALUES ('delete', old.id, old.content, old.keywords);
111
+ END;
112
+
113
+ CREATE TRIGGER IF NOT EXISTS memory_fts_update AFTER UPDATE ON memory BEGIN
114
+ INSERT INTO memory_fts(memory_fts, rowid, content, keywords)
115
+ VALUES ('delete', old.id, old.content, old.keywords);
116
+ INSERT INTO memory_fts(rowid, content, keywords)
117
+ VALUES (new.id, new.content, new.keywords);
118
+ END;
119
+ `);
120
+ }
121
+ finally {
122
+ db.close();
123
+ }
124
+ }
125
+ function listRecentSessions() {
126
+ const db = new better_sqlite3_1.default(exports.DB_PATH);
127
+ try {
128
+ const rows = db.prepare(`
129
+ WITH thread_last_ts AS (
130
+ SELECT
131
+ thread_id,
132
+ MAX(json_extract(CAST(checkpoint AS TEXT), '$.ts')) AS last_ts
133
+ FROM checkpoints
134
+ GROUP BY thread_id
135
+ )
136
+ SELECT
137
+ t.thread_id,
138
+ (SELECT json_extract(CAST(w.value AS TEXT), '$[0].kwargs.content')
139
+ FROM writes w
140
+ WHERE w.thread_id = t.thread_id
141
+ AND w.channel = 'messages'
142
+ AND json_extract(CAST(w.value AS TEXT), '$[0].id[2]') = 'HumanMessage'
143
+ ORDER BY w.checkpoint_id DESC
144
+ LIMIT 1) AS last_question,
145
+ t.last_ts
146
+ FROM thread_last_ts t
147
+ ORDER BY t.last_ts DESC
148
+ LIMIT 20
149
+ `).all();
150
+ return rows.map((r) => ({
151
+ thread_id: r.thread_id,
152
+ last_question: (0, utils_1.truncate)(r.last_question, 50),
153
+ last_ts: (0, utils_1.formatRelativeTime)(r.last_ts),
154
+ }));
155
+ }
156
+ finally {
157
+ db.close();
158
+ }
159
+ }
@@ -0,0 +1,27 @@
1
+ import { HookConfig, HooksConfig } from './config';
2
+ export type { HookConfig, HooksConfig };
3
+ export type HookResult = {
4
+ action: 'continue';
5
+ } | {
6
+ action: 'block';
7
+ reason: string;
8
+ } | {
9
+ action: 'inject';
10
+ message: string;
11
+ };
12
+ export declare function loadHooksConfig(): HooksConfig;
13
+ export declare function clearHooksCache(): void;
14
+ export declare function matchHooks(hooks: HookConfig[] | undefined, toolName: string): HookConfig[];
15
+ export declare function runHook(hook: HookConfig, env: Record<string, string>, timeout?: number): Promise<HookResult>;
16
+ export interface ToolHookContext {
17
+ toolName: string;
18
+ toolArgs: any;
19
+ toolCallId: string;
20
+ threadId: string;
21
+ }
22
+ export declare function runPreToolUseHooks(context: ToolHookContext): Promise<HookResult>;
23
+ export interface PostToolHookContext extends ToolHookContext {
24
+ toolOutput: string;
25
+ }
26
+ export declare function runPostToolUseHooks(context: PostToolHookContext): Promise<HookResult>;
27
+ export declare function runSessionStartHooks(threadId: string): Promise<void>;
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadHooksConfig = loadHooksConfig;
4
+ exports.clearHooksCache = clearHooksCache;
5
+ exports.matchHooks = matchHooks;
6
+ exports.runHook = runHook;
7
+ exports.runPreToolUseHooks = runPreToolUseHooks;
8
+ exports.runPostToolUseHooks = runPostToolUseHooks;
9
+ exports.runSessionStartHooks = runSessionStartHooks;
10
+ const child_process_1 = require("child_process");
11
+ const util_1 = require("util");
12
+ const config_1 = require("./config");
13
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
14
+ function loadHooksConfig() {
15
+ return (0, config_1.getHooksConfig)();
16
+ }
17
+ function clearHooksCache() {
18
+ (0, config_1.clearConfigCache)();
19
+ }
20
+ function matchHooks(hooks, toolName) {
21
+ if (!hooks)
22
+ return [];
23
+ return hooks.filter((h) => h.matcher === '*' || toolName.includes(h.matcher));
24
+ }
25
+ async function runHook(hook, env, timeout = 30000) {
26
+ const hookType = env.ZHITALK_HOOK_TYPE || 'hook';
27
+ console.log(`[Hook ${hookType}] ${hook.command}`);
28
+ try {
29
+ await execAsync(hook.command, {
30
+ cwd: process.cwd(),
31
+ env: { ...process.env, ...env },
32
+ timeout,
33
+ });
34
+ return { action: 'continue' };
35
+ }
36
+ catch (error) {
37
+ const code = error.code;
38
+ const stderr = error.stderr || '';
39
+ if (code === 1) {
40
+ return { action: 'block', reason: stderr };
41
+ }
42
+ else if (code === 2) {
43
+ return { action: 'inject', message: stderr };
44
+ }
45
+ return {
46
+ action: 'block',
47
+ reason: stderr || `Hook exited with code ${code}`,
48
+ };
49
+ }
50
+ }
51
+ async function runPreToolUseHooks(context) {
52
+ const config = loadHooksConfig();
53
+ const hooks = matchHooks(config.hooks.PreToolUse, context.toolName);
54
+ const injectMessages = [];
55
+ for (const hook of hooks) {
56
+ const result = await runHook(hook, {
57
+ ZHITALK_HOOK_TYPE: 'PreToolUse',
58
+ ZHITALK_TOOL_NAME: context.toolName,
59
+ ZHITALK_TOOL_ARGS: JSON.stringify(context.toolArgs),
60
+ ZHITALK_TOOL_CALL_ID: context.toolCallId,
61
+ ZHITALK_THREAD_ID: context.threadId,
62
+ });
63
+ if (result.action === 'block') {
64
+ return result;
65
+ }
66
+ if (result.action === 'inject') {
67
+ injectMessages.push(result.message);
68
+ }
69
+ }
70
+ if (injectMessages.length > 0) {
71
+ return { action: 'inject', message: injectMessages.join('\n') };
72
+ }
73
+ return { action: 'continue' };
74
+ }
75
+ async function runPostToolUseHooks(context) {
76
+ const config = loadHooksConfig();
77
+ const hooks = matchHooks(config.hooks.PostToolUse, context.toolName);
78
+ const injectMessages = [];
79
+ for (const hook of hooks) {
80
+ const result = await runHook(hook, {
81
+ ZHITALK_HOOK_TYPE: 'PostToolUse',
82
+ ZHITALK_TOOL_NAME: context.toolName,
83
+ ZHITALK_TOOL_ARGS: JSON.stringify(context.toolArgs),
84
+ ZHITALK_TOOL_OUTPUT: context.toolOutput,
85
+ ZHITALK_TOOL_CALL_ID: context.toolCallId,
86
+ ZHITALK_THREAD_ID: context.threadId,
87
+ });
88
+ if (result.action === 'block') {
89
+ return result;
90
+ }
91
+ if (result.action === 'inject') {
92
+ injectMessages.push(result.message);
93
+ }
94
+ }
95
+ if (injectMessages.length > 0) {
96
+ return { action: 'inject', message: injectMessages.join('\n') };
97
+ }
98
+ return { action: 'continue' };
99
+ }
100
+ async function runSessionStartHooks(threadId) {
101
+ const config = loadHooksConfig();
102
+ const hooks = config.hooks.SessionStart || [];
103
+ for (const hook of hooks) {
104
+ const result = await runHook(hook, {
105
+ ZHITALK_HOOK_TYPE: 'SessionStart',
106
+ ZHITALK_THREAD_ID: threadId,
107
+ });
108
+ if (result.action === 'block') {
109
+ console.error(`[SessionStart hook blocked] ${result.reason}`);
110
+ }
111
+ else if (result.action === 'inject') {
112
+ console.log(result.message);
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,25 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
3
+ export interface McpServerConfig {
4
+ command?: string;
5
+ args?: string[];
6
+ env?: Record<string, string>;
7
+ url?: string;
8
+ headers?: Record<string, string>;
9
+ }
10
+ export interface McpToolInfo {
11
+ name: string;
12
+ description?: string;
13
+ inputSchema: object;
14
+ }
15
+ export interface McpServerConnection {
16
+ name: string;
17
+ client: Client;
18
+ transport: Transport;
19
+ tools: McpToolInfo[];
20
+ }
21
+ export declare function loadMcpConfig(): Record<string, McpServerConfig>;
22
+ export declare function connectMcpServer(name: string, config: McpServerConfig): Promise<McpServerConnection>;
23
+ export declare function initializeMcpClients(): Promise<McpServerConnection[]>;
24
+ export declare function callMcpTool(client: Client, name: string, args: Record<string, unknown>): Promise<string>;
25
+ export declare function disconnectAllMcpClients(connections: McpServerConnection[]): Promise<void>;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadMcpConfig = loadMcpConfig;
4
+ exports.connectMcpServer = connectMcpServer;
5
+ exports.initializeMcpClients = initializeMcpClients;
6
+ exports.callMcpTool = callMcpTool;
7
+ exports.disconnectAllMcpClients = disconnectAllMcpClients;
8
+ const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
9
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
10
+ const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
11
+ const colors_1 = require("../colors");
12
+ const config_1 = require("../config");
13
+ const CONNECT_TIMEOUT_MS = 60000;
14
+ function loadMcpConfig() {
15
+ return (0, config_1.getMCPServerConfig)();
16
+ }
17
+ async function withTimeout(promise, ms, label) {
18
+ return Promise.race([
19
+ promise,
20
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms)),
21
+ ]);
22
+ }
23
+ function createMcpTransport(config) {
24
+ if (config.url) {
25
+ const url = new URL(config.url);
26
+ const requestInit = config.headers
27
+ ? { headers: config.headers }
28
+ : undefined;
29
+ return new streamableHttp_js_1.StreamableHTTPClientTransport(url, { requestInit });
30
+ }
31
+ if (config.command) {
32
+ return new stdio_js_1.StdioClientTransport({
33
+ command: config.command,
34
+ args: config.args,
35
+ env: config.env,
36
+ });
37
+ }
38
+ throw new Error('Invalid MCP server config: must have either "command" or "url"');
39
+ }
40
+ async function connectMcpServer(name, config) {
41
+ const transport = createMcpTransport(config);
42
+ const client = new index_js_1.Client({ name: 'zhitalk', version: '0.0.1' }, { capabilities: {} });
43
+ await withTimeout(client.connect(transport), CONNECT_TIMEOUT_MS, `MCP server "${name}" connect`);
44
+ const toolsResult = await withTimeout(client.listTools(), CONNECT_TIMEOUT_MS, `MCP server "${name}" listTools`);
45
+ const tools = (toolsResult.tools || []).map((t) => ({
46
+ name: t.name,
47
+ description: t.description,
48
+ inputSchema: t.inputSchema,
49
+ }));
50
+ return { name, client, transport, tools };
51
+ }
52
+ async function initializeMcpClients() {
53
+ const config = loadMcpConfig();
54
+ const entries = Object.entries(config);
55
+ if (entries.length === 0) {
56
+ return [];
57
+ }
58
+ console.log(colors_1.color.info(`[MCP] Connecting to ${entries.length} server(s)...`));
59
+ const results = await Promise.allSettled(entries.map(([name, cfg]) => connectMcpServer(name, cfg).catch((err) => {
60
+ const msg = err.message || '';
61
+ const hint = msg.includes('timed out')
62
+ ? ' (Hint: if using npx, the first run may need to download the package. Consider pre-installing with `npm install -g <package>` or increasing timeout.)'
63
+ : '';
64
+ console.error(colors_1.color.error(`[MCP] Failed to connect "${name}": ${msg}${hint}`));
65
+ throw err;
66
+ })));
67
+ const connections = [];
68
+ for (let i = 0; i < results.length; i++) {
69
+ const result = results[i];
70
+ if (result.status === 'fulfilled') {
71
+ const conn = result.value;
72
+ console.log(colors_1.color.good(`[MCP] Connected "${conn.name}" with ${conn.tools.length} tool(s)`));
73
+ connections.push(conn);
74
+ }
75
+ else {
76
+ console.error(colors_1.color.error(`[MCP] Skipped "${entries[i][0]}" due to connection error`));
77
+ }
78
+ }
79
+ return connections;
80
+ }
81
+ async function callMcpTool(client, name, args) {
82
+ const result = await client.callTool({ name, arguments: args });
83
+ if (result.isError) {
84
+ const text = extractTextFromResult(result);
85
+ throw new Error(text || `MCP tool "${name}" returned an error`);
86
+ }
87
+ return extractTextFromResult(result);
88
+ }
89
+ function extractTextFromResult(result) {
90
+ if (!result.content || !Array.isArray(result.content)) {
91
+ return JSON.stringify(result);
92
+ }
93
+ const texts = [];
94
+ for (const item of result.content) {
95
+ if (item.type === 'text' && typeof item.text === 'string') {
96
+ texts.push(item.text);
97
+ }
98
+ }
99
+ if (texts.length === 0) {
100
+ return JSON.stringify(result);
101
+ }
102
+ return texts.join('\n');
103
+ }
104
+ async function disconnectAllMcpClients(connections) {
105
+ await Promise.allSettled(connections.map(async (conn) => {
106
+ try {
107
+ await conn.transport.close();
108
+ }
109
+ catch {
110
+ // ignore
111
+ }
112
+ }));
113
+ }
@@ -0,0 +1,4 @@
1
+ import type { ZhitalkTool } from '../tools';
2
+ export declare function initMcpTools(): Promise<ZhitalkTool[]>;
3
+ export declare function getMcpTools(): ZhitalkTool[];
4
+ export declare function shutdownMcp(): Promise<void>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initMcpTools = initMcpTools;
4
+ exports.getMcpTools = getMcpTools;
5
+ exports.shutdownMcp = shutdownMcp;
6
+ const client_1 = require("./client");
7
+ const wrapper_1 = require("./wrapper");
8
+ let mcpConnections = [];
9
+ let mcpTools = [];
10
+ async function initMcpTools() {
11
+ mcpConnections = await (0, client_1.initializeMcpClients)();
12
+ mcpTools = [];
13
+ for (const conn of mcpConnections) {
14
+ for (const mcpTool of conn.tools) {
15
+ mcpTools.push((0, wrapper_1.wrapMcpTool)(conn, mcpTool));
16
+ }
17
+ }
18
+ return mcpTools;
19
+ }
20
+ function getMcpTools() {
21
+ return mcpTools;
22
+ }
23
+ async function shutdownMcp() {
24
+ await (0, client_1.disconnectAllMcpClients)(mcpConnections);
25
+ mcpConnections = [];
26
+ mcpTools = [];
27
+ }
@@ -0,0 +1,7 @@
1
+ import { type McpServerConnection } from './client';
2
+ import type { ZhitalkTool } from '../tools';
3
+ export declare function wrapMcpTool(connection: McpServerConnection, mcpTool: {
4
+ name: string;
5
+ description?: string;
6
+ inputSchema: object;
7
+ }): ZhitalkTool;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wrapMcpTool = wrapMcpTool;
4
+ const tools_1 = require("@langchain/core/tools");
5
+ const client_1 = require("./client");
6
+ const MCP_TOOL_PERMISSION_LEVEL = 'mcp';
7
+ function wrapMcpTool(connection, mcpTool) {
8
+ const prefixedName = `${connection.name}_${mcpTool.name}`;
9
+ const schemaJson = JSON.stringify(mcpTool.inputSchema, null, 2);
10
+ const description = `[MCP:${connection.name}] ${mcpTool.description || 'No description'}\n\nParameters schema:\n${schemaJson}`;
11
+ // Pass the MCP server's JSON Schema directly to LangChain so the LLM
12
+ // sees the real parameter requirements instead of a shapeless passthrough.
13
+ const schema = mcpTool.inputSchema;
14
+ const impl = async (args) => {
15
+ const result = await (0, client_1.callMcpTool)(connection.client, mcpTool.name, args);
16
+ return result;
17
+ };
18
+ const t = (0, tools_1.tool)(impl, {
19
+ name: prefixedName,
20
+ description,
21
+ schema,
22
+ });
23
+ t.permission_level = MCP_TOOL_PERMISSION_LEVEL;
24
+ return t;
25
+ }
@@ -0,0 +1,5 @@
1
+ import { ChatOpenAI } from '@langchain/openai';
2
+ export declare function createModel(options?: {
3
+ streaming?: boolean;
4
+ }): ChatOpenAI;
5
+ export declare function checkModel(): Promise<void>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createModel = createModel;
4
+ exports.checkModel = checkModel;
5
+ const openai_1 = require("@langchain/openai");
6
+ const config_1 = require("./config");
7
+ const modelConfig = (0, config_1.getModelConfig)();
8
+ function createModel(options) {
9
+ return new openai_1.ChatOpenAI({
10
+ model: modelConfig.model,
11
+ apiKey: modelConfig.apiKey,
12
+ configuration: {
13
+ baseURL: modelConfig.baseURL,
14
+ },
15
+ streaming: options?.streaming ?? true,
16
+ modelKwargs: {
17
+ thinking: { type: 'disabled' },
18
+ },
19
+ });
20
+ }
21
+ async function checkModel() {
22
+ if (modelConfig.apiKey.length < 20) {
23
+ try {
24
+ const model = createModel({ streaming: false });
25
+ await model.invoke([{ role: 'user', content: 'hi' }]);
26
+ }
27
+ catch {
28
+ throw new Error(`API Key 验证失败,请检查配置是否正确\n\n请参考 https://zhitalk.chat/#config 修改配置`);
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,115 @@
1
+ {
2
+ "macos": [
3
+ "~/.ssh",
4
+ "~/.gnupg",
5
+ "~/.aws",
6
+ "~/.azure",
7
+ "~/.config/gcloud",
8
+ "~/.kube",
9
+ "~/.docker",
10
+ "~/.netrc",
11
+ "~/Library/Keychains",
12
+ "~/Library/Application Support/Google/Chrome",
13
+ "~/Library/Application Support/Chromium",
14
+ "~/Library/Application Support/Firefox",
15
+ "~/Library/Application Support/Slack",
16
+ "~/Library/Application Support/Discord",
17
+ "~/Library/Application Support/Telegram",
18
+ "~/Library/Application Support/Signal",
19
+ "~/.zshrc",
20
+ "~/.bashrc",
21
+ "~/.bash_profile",
22
+ "~/.profile",
23
+ "~/.env",
24
+ "~/.env.*",
25
+ "~/.gitconfig",
26
+ "~/.git-credentials",
27
+ "~/.npmrc",
28
+ "~/.pnpmrc",
29
+ "~/.yarnrc",
30
+ "~/.pypirc",
31
+ "~/.m2",
32
+ "~/.gradle",
33
+ "~/.terraform",
34
+ "~/.config/gh",
35
+ "~/.config/gitlab",
36
+ "~/.circleci",
37
+ "~/.vercel",
38
+ "~/.netlify",
39
+ "~/Library/Containers",
40
+ "/private",
41
+ "/etc",
42
+ "/var"
43
+ ],
44
+ "linux": [
45
+ "~/.ssh",
46
+ "~/.gnupg",
47
+ "~/.pki",
48
+ "~/.aws",
49
+ "~/.azure",
50
+ "~/.config/gcloud",
51
+ "~/.kube",
52
+ "~/.docker",
53
+ "~/.netrc",
54
+ "~/.local/share/keyrings",
55
+ "~/.config/google-chrome",
56
+ "~/.config/chromium",
57
+ "~/.mozilla/firefox",
58
+ "~/.config/Slack",
59
+ "~/.config/discord",
60
+ "~/.local/share/TelegramDesktop",
61
+ "~/.zshrc",
62
+ "~/.bashrc",
63
+ "~/.bash_profile",
64
+ "~/.profile",
65
+ "~/.env",
66
+ "~/.env.*",
67
+ "~/.gitconfig",
68
+ "~/.git-credentials",
69
+ "~/.npmrc",
70
+ "~/.pnpmrc",
71
+ "~/.yarnrc",
72
+ "~/.pypirc",
73
+ "~/.m2",
74
+ "~/.gradle",
75
+ "~/.terraform",
76
+ "~/.config/gh",
77
+ "~/.config/gitlab",
78
+ "~/.circleci",
79
+ "~/.vercel",
80
+ "~/.netlify",
81
+ "/etc/shadow",
82
+ "/etc/sudoers",
83
+ "/proc",
84
+ "/sys",
85
+ "/var/lib",
86
+ "/root"
87
+ ],
88
+ "windows": [
89
+ "%USERPROFILE%\\.ssh",
90
+ "%USERPROFILE%\\.gnupg",
91
+ "%USERPROFILE%\\.aws",
92
+ "%USERPROFILE%\\.azure",
93
+ "%USERPROFILE%\\.kube",
94
+ "%USERPROFILE%\\.docker",
95
+ "%LOCALAPPDATA%\\Google\\Chrome\\User Data",
96
+ "%LOCALAPPDATA%\\Chromium\\User Data",
97
+ "%APPDATA%\\Mozilla\\Firefox",
98
+ "%APPDATA%\\Slack",
99
+ "%APPDATA%\\Discord",
100
+ "%APPDATA%\\Telegram Desktop",
101
+ "%USERPROFILE%\\.gitconfig",
102
+ "%USERPROFILE%\\.git-credentials",
103
+ "%USERPROFILE%\\.npmrc",
104
+ "%USERPROFILE%\\.pnpmrc",
105
+ "%USERPROFILE%\\.yarnrc",
106
+ "%USERPROFILE%\\.m2",
107
+ "%USERPROFILE%\\.gradle",
108
+ "%APPDATA%",
109
+ "%LOCALAPPDATA%",
110
+ "C:\\Windows\\System32",
111
+ "C:\\Windows\\System32\\config\\SAM",
112
+ "C:\\Windows\\System32\\config\\SECURITY",
113
+ "C:\\Windows\\System32\\config\\SYSTEM"
114
+ ]
115
+ }
@@ -0,0 +1,11 @@
1
+ export declare function checkExecPermission(toolCall: {
2
+ name: string;
3
+ args: Record<string, any>;
4
+ }): {
5
+ action: 'allow';
6
+ } | {
7
+ action: 'block';
8
+ reason: string;
9
+ } | {
10
+ action: 'confirm';
11
+ };