@pheem49/mint 1.4.0 → 1.4.1
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/.codex +0 -0
- package/README.md +171 -127
- package/main.js +21 -1
- package/mint-cli-logic.js +21 -1
- package/mint-cli.js +89 -22
- package/package.json +1 -1
- package/src/AI_Brain/Gemini_API.js +38 -24
- package/src/AI_Brain/proactive_engine.js +2 -8
- package/src/Automation_Layer/file_operations.js +123 -4
- package/src/Automation_Layer/open_app.js +72 -43
- package/src/Automation_Layer/open_website.js +3 -3
- package/src/CLI/chat_router.js +51 -18
- package/src/CLI/chat_ui.js +34 -10
- package/src/CLI/code_agent.js +113 -13
- package/src/CLI/workspace_manager.js +15 -6
- package/src/Plugins/docker.js +12 -10
- package/src/System/custom_workflows.js +9 -2
- package/tests/chat_router.test.js +42 -0
- package/tests/code_agent.test.js +69 -0
- package/tests/docker.test.js +46 -0
- package/tests/file_operations.test.js +57 -0
- package/tests/provider_routing.test.js +67 -0
- package/tests/workspace_manager.test.js +15 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests: file_operations helpers
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
|
|
9
|
+
describe('file_operations findPath', () => {
|
|
10
|
+
let tempDir;
|
|
11
|
+
let originalCwd;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
jest.resetModules();
|
|
15
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mint-file-ops-'));
|
|
16
|
+
originalCwd = process.cwd();
|
|
17
|
+
process.chdir(tempDir);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
process.chdir(originalCwd);
|
|
22
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('finds directory matches by name', () => {
|
|
26
|
+
const targetDir = path.join(tempDir, 'nested', 'xidaidai');
|
|
27
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
28
|
+
|
|
29
|
+
const { findPath } = require('../src/Automation_Layer/file_operations');
|
|
30
|
+
const result = findPath('xidaidai', { type: 'dir', maxResults: 10, roots: [tempDir] });
|
|
31
|
+
|
|
32
|
+
expect(result.success).toBe(true);
|
|
33
|
+
expect(result.matches.some(match => match.path === targetDir && match.type === 'dir')).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('returns not found message when no path matches', () => {
|
|
37
|
+
const { findPath } = require('../src/Automation_Layer/file_operations');
|
|
38
|
+
const result = findPath('does-not-exist', { type: 'dir', maxResults: 10, roots: [tempDir] });
|
|
39
|
+
|
|
40
|
+
expect(result.success).toBe(false);
|
|
41
|
+
expect(result.message).toContain('ไม่พบ');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('prefers exact directory name matches over nested partial matches', () => {
|
|
45
|
+
const exactDir = path.join(tempDir, 'xidaidai');
|
|
46
|
+
const nestedPartial = path.join(tempDir, 'xidaidai collection', 'xidaidai gif');
|
|
47
|
+
fs.mkdirSync(exactDir, { recursive: true });
|
|
48
|
+
fs.mkdirSync(nestedPartial, { recursive: true });
|
|
49
|
+
|
|
50
|
+
const { findPath } = require('../src/Automation_Layer/file_operations');
|
|
51
|
+
const result = findPath('xidaidai', { type: 'dir', maxResults: 10, roots: [tempDir] });
|
|
52
|
+
|
|
53
|
+
expect(result.success).toBe(true);
|
|
54
|
+
expect(result.matches.length).toBe(1);
|
|
55
|
+
expect(result.matches[0].path).toBe(exactDir);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests: Gemini_API provider routing helpers
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
jest.mock('@google/genai', () => ({
|
|
6
|
+
GoogleGenAI: jest.fn(() => ({
|
|
7
|
+
chats: {
|
|
8
|
+
create: jest.fn(() => ({
|
|
9
|
+
sendMessage: jest.fn(),
|
|
10
|
+
sendMessageStream: jest.fn(),
|
|
11
|
+
getHistory: jest.fn(async () => [])
|
|
12
|
+
}))
|
|
13
|
+
},
|
|
14
|
+
models: {
|
|
15
|
+
generateContent: jest.fn()
|
|
16
|
+
}
|
|
17
|
+
}))
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
jest.mock('../src/System/chat_history_manager', () => ({
|
|
21
|
+
readChatHistory: jest.fn(() => []),
|
|
22
|
+
writeChatHistory: jest.fn(),
|
|
23
|
+
clearChatHistory: jest.fn()
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
jest.mock('../src/System/config_manager', () => ({
|
|
27
|
+
readConfig: jest.fn(() => ({})),
|
|
28
|
+
getAvailableProviders: jest.fn(() => ['ollama', 'gemini'])
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
jest.mock('../src/Plugins/plugin_manager', () => ({
|
|
32
|
+
loadPlugins: jest.fn(),
|
|
33
|
+
getPromptDescriptions: jest.fn(() => '')
|
|
34
|
+
}));
|
|
35
|
+
|
|
36
|
+
jest.mock('../src/Plugins/mcp_manager', () => ({
|
|
37
|
+
getAllTools: jest.fn(() => [])
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
jest.mock('../src/AI_Brain/memory_store', () => ({
|
|
41
|
+
getUserContext: jest.fn(() => ''),
|
|
42
|
+
getCachedResponse: jest.fn(),
|
|
43
|
+
recordInteraction: jest.fn(),
|
|
44
|
+
cacheResponse: jest.fn()
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
jest.mock('../src/AI_Brain/agent_orchestrator', () => ({
|
|
48
|
+
getCurrentAgent: jest.fn(() => ({ name: 'Mint Default', instruction: 'default' }))
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
jest.mock('../src/CLI/workspace_manager', () => ({
|
|
52
|
+
getWorkspaceByPath: jest.fn(() => null)
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
describe('Gemini_API provider routing helpers', () => {
|
|
56
|
+
test('prioritizes configured provider, then falls back to available providers', () => {
|
|
57
|
+
const geminiApi = require('../src/AI_Brain/Gemini_API');
|
|
58
|
+
const order = geminiApi._helpers.getProviderAttemptOrder({
|
|
59
|
+
aiProvider: 'openai',
|
|
60
|
+
openaiApiKey: 'key',
|
|
61
|
+
localApiBaseUrl: 'http://localhost:1234/v1'
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
expect(order[0]).toBe('openai');
|
|
65
|
+
expect(order).toContain('ollama');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -9,13 +9,17 @@ const os = require('os');
|
|
|
9
9
|
|
|
10
10
|
describe('Workspace Manager', () => {
|
|
11
11
|
let tempDir;
|
|
12
|
+
let workspaceFile;
|
|
12
13
|
|
|
13
14
|
beforeEach(() => {
|
|
14
15
|
// Create a temp workspace directory
|
|
15
16
|
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mint-ws-test-'));
|
|
17
|
+
workspaceFile = path.join(tempDir, 'workspaces.json');
|
|
18
|
+
process.env.MINT_WORKSPACE_FILE = workspaceFile;
|
|
16
19
|
});
|
|
17
20
|
|
|
18
21
|
afterEach(() => {
|
|
22
|
+
delete process.env.MINT_WORKSPACE_FILE;
|
|
19
23
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
20
24
|
});
|
|
21
25
|
|
|
@@ -32,6 +36,17 @@ describe('Workspace Manager', () => {
|
|
|
32
36
|
expect(ws.name).toBe('test-ws');
|
|
33
37
|
});
|
|
34
38
|
|
|
39
|
+
test('does not match sibling paths with same prefix', () => {
|
|
40
|
+
const workspaceRoot = path.join(tempDir, 'project');
|
|
41
|
+
const siblingPath = path.join(tempDir, 'project-two');
|
|
42
|
+
fs.mkdirSync(workspaceRoot, { recursive: true });
|
|
43
|
+
fs.mkdirSync(siblingPath, { recursive: true });
|
|
44
|
+
|
|
45
|
+
wsManager.addWorkspace('test-ws', workspaceRoot);
|
|
46
|
+
const ws = wsManager.getWorkspaceByPath(siblingPath);
|
|
47
|
+
expect(ws).toBeNull();
|
|
48
|
+
});
|
|
49
|
+
|
|
35
50
|
test('removes workspaces', () => {
|
|
36
51
|
wsManager.addWorkspace('test-ws', tempDir);
|
|
37
52
|
wsManager.removeWorkspace('test-ws');
|