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,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
+ };
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkExecPermission = checkExecPermission;
4
+ const util_1 = require("./util");
5
+ function checkExecPermission(toolCall) {
6
+ const command = toolCall.args?.command;
7
+ if (typeof command !== 'string') {
8
+ return { action: 'confirm' };
9
+ }
10
+ if ((0, util_1.isSafeCommand)(command)) {
11
+ return { action: 'allow' };
12
+ }
13
+ if ((0, util_1.isChangingDirectory)(command)) {
14
+ return {
15
+ action: 'block',
16
+ reason: `命令包含切换目录操作,为防止目录逃逸,禁止执行。如有需要请手动操作。`,
17
+ };
18
+ }
19
+ const scriptCheck = (0, util_1.isScriptExecution)(command);
20
+ if (scriptCheck.blocked) {
21
+ return {
22
+ action: 'block',
23
+ reason: scriptCheck.reason,
24
+ };
25
+ }
26
+ const dangerCheck = (0, util_1.isDangerousOperation)(command);
27
+ if (dangerCheck.blocked) {
28
+ return {
29
+ action: 'block',
30
+ reason: dangerCheck.reason,
31
+ };
32
+ }
33
+ return { action: 'confirm' };
34
+ }
@@ -0,0 +1 @@
1
+ export declare function isDangerousPath(filepath: string): boolean;
@@ -0,0 +1,53 @@
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.isDangerousPath = isDangerousPath;
7
+ const path_1 = __importDefault(require("path"));
8
+ const os_1 = __importDefault(require("os"));
9
+ const dangerous_path_json_1 = __importDefault(require("./dangerous-path.json"));
10
+ function expandPath(filepath) {
11
+ let expanded = filepath;
12
+ if (expanded.startsWith('~')) {
13
+ expanded = path_1.default.join(os_1.default.homedir(), expanded.slice(1));
14
+ }
15
+ expanded = expanded.replace(/%USERPROFILE%/gi, os_1.default.homedir());
16
+ expanded = expanded.replace(/%APPDATA%/gi, process.env.APPDATA || path_1.default.join(os_1.default.homedir(), 'AppData', 'Roaming'));
17
+ expanded = expanded.replace(/%LOCALAPPDATA%/gi, process.env.LOCALAPPDATA || path_1.default.join(os_1.default.homedir(), 'AppData', 'Local'));
18
+ if (!path_1.default.isAbsolute(expanded)) {
19
+ expanded = path_1.default.resolve(expanded);
20
+ }
21
+ expanded = path_1.default.normalize(expanded);
22
+ return expanded;
23
+ }
24
+ function globToRegex(pattern) {
25
+ const escaped = pattern
26
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
27
+ .replace(/\*/g, '[^\\\\/]*');
28
+ return new RegExp(`^${escaped}(?:[\\\\/].*)?$`);
29
+ }
30
+ function isDangerousPath(filepath) {
31
+ const platform = process.platform === 'win32'
32
+ ? 'windows'
33
+ : process.platform === 'darwin'
34
+ ? 'macos'
35
+ : 'linux';
36
+ const dangerousList = dangerous_path_json_1.default[platform];
37
+ const expandedInput = expandPath(filepath);
38
+ for (const dangerous of dangerousList) {
39
+ const expandedDangerous = expandPath(dangerous);
40
+ if (dangerous.includes('*')) {
41
+ const regex = globToRegex(expandedDangerous);
42
+ if (regex.test(expandedInput))
43
+ return true;
44
+ }
45
+ else {
46
+ if (expandedInput === expandedDangerous)
47
+ return true;
48
+ if (expandedInput.startsWith(expandedDangerous + path_1.default.sep))
49
+ return true;
50
+ }
51
+ }
52
+ return false;
53
+ }
@@ -0,0 +1 @@
1
+ export declare function isSafeDomain(url: string): boolean;