@pheem49/mint 1.5.5 → 1.6.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/.github/FUNDING.yml +2 -0
- package/.github/workflows/ci.yml +45 -0
- package/.github/workflows/release.yml +79 -0
- package/Cargo.lock +5792 -0
- package/Cargo.toml +32 -0
- package/README.md +387 -353
- package/assets/icon.png +0 -0
- package/bin/mint +0 -0
- package/crates/mint-cli/Cargo.toml +23 -0
- package/crates/mint-cli/src/agent.rs +851 -0
- package/crates/mint-cli/src/gmail.rs +216 -0
- package/crates/mint-cli/src/image.rs +142 -0
- package/crates/mint-cli/src/main.rs +2837 -0
- package/crates/mint-cli/src/mcp.rs +63 -0
- package/crates/mint-cli/src/onboard.rs +1149 -0
- package/crates/mint-cli/src/setup.rs +390 -0
- package/crates/mint-cli/src/skills.rs +8 -0
- package/crates/mint-cli/src/updater.rs +279 -0
- package/crates/mint-core/Cargo.toml +22 -0
- package/crates/mint-core/src/agent_loop.rs +94 -0
- package/crates/mint-core/src/api_server.rs +991 -0
- package/crates/mint-core/src/channels.rs +248 -0
- package/crates/mint-core/src/chat.rs +895 -0
- package/crates/mint-core/src/code_tools.rs +729 -0
- package/crates/mint-core/src/config.rs +368 -0
- package/crates/mint-core/src/files.rs +159 -0
- package/crates/mint-core/src/knowledge.rs +541 -0
- package/crates/mint-core/src/lib.rs +84 -0
- package/crates/mint-core/src/mcp.rs +273 -0
- package/crates/mint-core/src/memory.rs +673 -0
- package/crates/mint-core/src/orchestration.rs +2157 -0
- package/crates/mint-core/src/pictures.rs +314 -0
- package/crates/mint-core/src/plugins.rs +727 -0
- package/crates/mint-core/src/safety.rs +416 -0
- package/crates/mint-core/src/semantic.rs +254 -0
- package/crates/mint-core/src/shell.rs +317 -0
- package/crates/mint-core/src/skills.rs +71 -0
- package/crates/mint-core/src/symbols.rs +157 -0
- package/crates/mint-core/src/tasks.rs +308 -0
- package/crates/mint-core/src/tts.rs +92 -0
- package/crates/mint-core/src/weather.rs +93 -0
- package/crates/mint-core/src/web_search.rs +200 -0
- package/crates/mint-core/src/workflows.rs +81 -0
- package/crates/mint-core/tests/mcp_stdio.rs +45 -0
- package/crates/mint-core/tests/memory_persistence.rs +172 -0
- package/crates/mint-core/tests/pictures_storage.rs +14 -0
- package/crates/mint-core/tests/task_lifecycle.rs +87 -0
- package/package.json +35 -99
- package/src/bin/index.js +16 -0
- package/src/renderer/index-web.html +17 -0
- package/src/renderer/index.html +17 -0
- package/src/renderer/public/Live2DCubismCore.js +9 -0
- package/src/renderer/public/assets/icon.png +0 -0
- package/src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.model3.json +36 -0
- package/src/renderer/src/App.tsx +33 -0
- package/src/renderer/src/calculator.ts +47 -0
- package/src/renderer/src/components/ChatPanel.tsx +1598 -0
- package/src/renderer/src/components/DashboardSidebar.tsx +358 -0
- package/src/renderer/src/components/Live2DStage.tsx +374 -0
- package/src/renderer/src/components/MintDashboard.tsx +950 -0
- package/src/renderer/src/components/ModelPanel.tsx +154 -0
- package/src/renderer/src/components/PicturesLibrary.tsx +46 -0
- package/src/renderer/src/components/ProactiveGlow.tsx +19 -0
- package/src/renderer/src/components/ScreenPicker.tsx +579 -0
- package/src/renderer/src/components/SettingsWindow.tsx +1467 -0
- package/src/renderer/src/components/SpotlightWindow.tsx +280 -0
- package/src/renderer/src/components/WidgetWindow.tsx +36 -0
- package/src/renderer/src/components/WorkspacePanel.tsx +268 -0
- package/src/{UI → renderer/src/css}/settings.css +69 -16
- package/src/renderer/src/css/spotlight.css +113 -0
- package/src/renderer/src/css/styles.css +3722 -0
- package/src/renderer/src/css/widget.css +185 -0
- package/src/renderer/src/env.d.ts +116 -0
- package/src/renderer/src/index.css +379 -0
- package/src/renderer/src/main.tsx +13 -0
- package/src/renderer/src/tauri.ts +996 -0
- package/src/renderer/src-web/App.tsx +25 -0
- package/src/renderer/src-web/calculator.ts +47 -0
- package/src/renderer/src-web/components/ChatPanel.tsx +1662 -0
- package/src/renderer/src-web/components/DashboardSidebar.tsx +242 -0
- package/src/renderer/src-web/components/MintDashboard.tsx +763 -0
- package/src/renderer/src-web/components/PicturesLibrary.tsx +73 -0
- package/src/renderer/src-web/components/SettingsWindow.tsx +1500 -0
- package/src/renderer/src-web/css/settings.css +1100 -0
- package/src/{UI → renderer/src-web/css}/spotlight.css +4 -4
- package/src/{UI → renderer/src-web/css}/styles.css +1055 -159
- package/src/{UI → renderer/src-web/css}/widget.css +2 -2
- package/src/renderer/src-web/env.d.ts +107 -0
- package/src/renderer/src-web/index.css +379 -0
- package/src/renderer/src-web/main.tsx +13 -0
- package/src/renderer/src-web/tauri.ts +983 -0
- package/tsconfig.json +30 -0
- package/vite.config.ts +33 -0
- package/vite.config.web.ts +51 -0
- package/GUIDE_TH.md +0 -125
- package/assets/Agent_Mint.png +0 -0
- package/assets/CLI_Screen.png +0 -0
- package/assets/Settings.png +0 -0
- package/benchmark_ai.js +0 -71
- package/install.ps1 +0 -64
- package/install.sh +0 -54
- package/main.js +0 -139
- package/mint-cli-logic.js +0 -3
- package/mint-cli.js +0 -410
- package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.model3.json +0 -47
- package/models/Shiroko_Model/Shiroko//342/232/241/351/253/230/344/272/256/342/232/241/344/275/277/347/224/250/346/225/231/347/250/213/344/270/216/346/263/250/346/204/217/344/272/213/351/241/271.txt +0 -23
- package/preload-picker.js +0 -11
- package/preload-settings.js +0 -11
- package/preload.js +0 -41
- package/scripts/install_linux_desktop_entry.js +0 -48
- package/src/AI_Brain/Gemini_API.js +0 -813
- package/src/AI_Brain/agent_orchestrator.js +0 -73
- package/src/AI_Brain/autonomous_brain.js +0 -179
- package/src/AI_Brain/behavior_memory.js +0 -135
- package/src/AI_Brain/headless_agent.js +0 -143
- package/src/AI_Brain/knowledge_base.js +0 -349
- package/src/AI_Brain/memory_store.js +0 -662
- package/src/AI_Brain/proactive_engine.js +0 -172
- package/src/AI_Brain/provider_adapter.js +0 -365
- package/src/Automation_Layer/browser_automation.js +0 -149
- package/src/Automation_Layer/file_operations.js +0 -286
- package/src/Automation_Layer/open_app.js +0 -85
- package/src/Automation_Layer/open_website.js +0 -38
- package/src/CLI/approval_handler.js +0 -47
- package/src/CLI/chat_router.js +0 -247
- package/src/CLI/chat_ui.js +0 -1159
- package/src/CLI/cli_colors.js +0 -115
- package/src/CLI/cli_formatters.js +0 -94
- package/src/CLI/code_agent.js +0 -1667
- package/src/CLI/code_session_memory.js +0 -62
- package/src/CLI/gmail_auth.js +0 -210
- package/src/CLI/image_input.js +0 -90
- package/src/CLI/intent_detectors.js +0 -181
- package/src/CLI/interactive_chat.js +0 -658
- package/src/CLI/list_features.js +0 -64
- package/src/CLI/onboarding.js +0 -416
- package/src/CLI/repo_summarizer.js +0 -282
- package/src/CLI/semantic_code_search.js +0 -312
- package/src/CLI/skill_manager.js +0 -41
- package/src/CLI/slash_command_handler.js +0 -418
- package/src/CLI/symbol_indexer.js +0 -231
- package/src/CLI/updater.js +0 -230
- package/src/CLI/workspace_manager.js +0 -90
- package/src/Channels/brave_search_bridge.js +0 -35
- package/src/Channels/discord_bridge.js +0 -66
- package/src/Channels/google_search_bridge.js +0 -38
- package/src/Channels/line_bridge.js +0 -60
- package/src/Channels/slack_bridge.js +0 -48
- package/src/Channels/telegram_bridge.js +0 -41
- package/src/Channels/whatsapp_bridge.js +0 -57
- package/src/Command_Parser/parser.js +0 -45
- package/src/Plugins/dev_tools.js +0 -41
- package/src/Plugins/discord.js +0 -20
- package/src/Plugins/docker.js +0 -47
- package/src/Plugins/gmail.js +0 -251
- package/src/Plugins/google_calendar.js +0 -252
- package/src/Plugins/mcp_manager.js +0 -95
- package/src/Plugins/notion.js +0 -256
- package/src/Plugins/obsidian.js +0 -54
- package/src/Plugins/plugin_manager.js +0 -81
- package/src/Plugins/spotify.js +0 -173
- package/src/Plugins/system_metrics.js +0 -31
- package/src/Plugins/system_monitor.js +0 -72
- package/src/System/action_executor.js +0 -178
- package/src/System/bridge_manager.js +0 -76
- package/src/System/chat_history_manager.js +0 -83
- package/src/System/config_manager.js +0 -194
- package/src/System/custom_workflows.js +0 -163
- package/src/System/daemon_manager.js +0 -67
- package/src/System/google_tts_urls.js +0 -51
- package/src/System/granular_automation.js +0 -157
- package/src/System/ipc_handlers.js +0 -332
- package/src/System/notifications.js +0 -23
- package/src/System/optional_require.js +0 -23
- package/src/System/picture_store.js +0 -109
- package/src/System/proactive_loop.js +0 -153
- package/src/System/safety_manager.js +0 -273
- package/src/System/sandbox_runner.js +0 -182
- package/src/System/screen_capture.js +0 -175
- package/src/System/smart_context.js +0 -227
- package/src/System/system_automation.js +0 -162
- package/src/System/system_events.js +0 -79
- package/src/System/system_info.js +0 -125
- package/src/System/task_manager.js +0 -222
- package/src/System/tool_registry.js +0 -293
- package/src/System/window_manager.js +0 -220
- package/src/UI/floating.css +0 -80
- package/src/UI/floating.html +0 -17
- package/src/UI/floating.js +0 -67
- package/src/UI/live2d_manager.js +0 -600
- package/src/UI/preload-floating.js +0 -7
- package/src/UI/preload-spotlight.js +0 -11
- package/src/UI/preload-widget.js +0 -5
- package/src/UI/proactive-glow.html +0 -42
- package/src/UI/renderer.js +0 -2127
- package/src/UI/screenPicker.html +0 -214
- package/src/UI/screenPicker.js +0 -262
- package/src/UI/settings.html +0 -577
- package/src/UI/settings.js +0 -770
- package/src/UI/spotlight.html +0 -23
- package/src/UI/spotlight.js +0 -185
- package/src/UI/widget.html +0 -29
- package/src/UI/widget.js +0 -10
- /package/{models → src/renderer/public/models}/Shiroko_Model/Shiroko/Shiroko_Core/72d86db84cfa9730b894c241fd24c0db.png +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//345/233/264/350/243/231.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/apron.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/214/253/345/222/252/346/273/244/351/225/234.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/catfilter.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/202/271/344/270/200/344/270/213.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/click.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//345/221/206/347/214/253.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/dazed.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//345/221/206/347/214/253/347/234/274/347/217/240/346/221/207/346/231/203.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/dazedeyes.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/234/274/351/225/234.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/glasses.exp3.json} +0 -0
- /package/{models → src/renderer/public/models}/Shiroko_Model/Shiroko/Shiroko_Core/items_pinned_to_model.json +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//346/213/277/347/254/224.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/pen.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//346/213/215/347/205/247.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/photo.exp3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_00.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_00.png} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_01.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_01.png} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_02.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_02.png} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_03.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_03.png} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.cdi3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.cdi3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.moc3" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.moc3} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.physics3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.physics3.json} +0 -0
- /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.vtube.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.vtube.json} +0 -0
package/src/CLI/updater.js
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
const { execFile } = require('child_process');
|
|
2
|
-
const pkg = require('../../package.json');
|
|
3
|
-
|
|
4
|
-
const NPM_COMMAND = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
5
|
-
const DEFAULT_AUTO_UPDATE_INTERVAL_HOURS = 24;
|
|
6
|
-
|
|
7
|
-
function execFilePromise(command, args, options = {}) {
|
|
8
|
-
return new Promise((resolve, reject) => {
|
|
9
|
-
execFile(command, args, options, (error, stdout, stderr) => {
|
|
10
|
-
if (error) {
|
|
11
|
-
error.stdout = stdout;
|
|
12
|
-
error.stderr = stderr;
|
|
13
|
-
reject(error);
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
resolve({ stdout, stderr });
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function parseVersion(version) {
|
|
22
|
-
return String(version || '')
|
|
23
|
-
.trim()
|
|
24
|
-
.replace(/^v/, '')
|
|
25
|
-
.split('-')[0]
|
|
26
|
-
.split('.')
|
|
27
|
-
.map((part) => Number.parseInt(part, 10) || 0);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function compareVersions(a, b) {
|
|
31
|
-
const left = parseVersion(a);
|
|
32
|
-
const right = parseVersion(b);
|
|
33
|
-
const length = Math.max(left.length, right.length, 3);
|
|
34
|
-
|
|
35
|
-
for (let i = 0; i < length; i++) {
|
|
36
|
-
const l = left[i] || 0;
|
|
37
|
-
const r = right[i] || 0;
|
|
38
|
-
if (l > r) return 1;
|
|
39
|
-
if (l < r) return -1;
|
|
40
|
-
}
|
|
41
|
-
return 0;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function normalizeNpmVersionOutput(output) {
|
|
45
|
-
const trimmed = String(output || '').trim();
|
|
46
|
-
if (!trimmed) return '';
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
const parsed = JSON.parse(trimmed);
|
|
50
|
-
if (typeof parsed === 'string') return parsed;
|
|
51
|
-
} catch (err) {
|
|
52
|
-
// npm may return plain text depending on config/version.
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return trimmed.replace(/^['"]|['"]$/g, '');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function getAutoUpdateIntervalMs(config = {}) {
|
|
59
|
-
const hours = Number(config.autoUpdateCheckIntervalHours);
|
|
60
|
-
const safeHours = Number.isFinite(hours) && hours > 0
|
|
61
|
-
? hours
|
|
62
|
-
: DEFAULT_AUTO_UPDATE_INTERVAL_HOURS;
|
|
63
|
-
return safeHours * 60 * 60 * 1000;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function shouldRunAutoUpdate(config = {}, now = Date.now()) {
|
|
67
|
-
if (config.enableAutoUpdate === false) return false;
|
|
68
|
-
|
|
69
|
-
const lastCheck = Date.parse(config.lastUpdateCheckAt || '');
|
|
70
|
-
if (!Number.isFinite(lastCheck)) return true;
|
|
71
|
-
|
|
72
|
-
return now - lastCheck >= getAutoUpdateIntervalMs(config);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async function getLatestVersion(packageName = pkg.name) {
|
|
76
|
-
const { stdout } = await execFilePromise(NPM_COMMAND, ['view', packageName, 'version', '--json'], {
|
|
77
|
-
maxBuffer: 1024 * 1024,
|
|
78
|
-
timeout: 30000
|
|
79
|
-
});
|
|
80
|
-
return normalizeNpmVersionOutput(stdout);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async function installLatest(packageName = pkg.name, options = {}) {
|
|
84
|
-
const args = ['install', '-g', `${packageName}@latest`];
|
|
85
|
-
if (options.dryRun) {
|
|
86
|
-
args.push('--dry-run');
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return await execFilePromise(NPM_COMMAND, args, {
|
|
90
|
-
maxBuffer: 1024 * 1024 * 8,
|
|
91
|
-
timeout: 5 * 60 * 1000
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function formatUpdateError(error) {
|
|
96
|
-
const detail = [error.stderr, error.stdout, error.message].filter(Boolean).join('\n').trim();
|
|
97
|
-
if (/EACCES|permission denied|Access is denied/i.test(detail)) {
|
|
98
|
-
return [
|
|
99
|
-
'Update failed because npm does not have permission to modify the global install directory.',
|
|
100
|
-
`Run manually: npm install -g ${pkg.name}@latest`,
|
|
101
|
-
'If your npm global packages require sudo, run that command with sudo.'
|
|
102
|
-
].join('\n');
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (/E404|404 Not Found|not in this registry/i.test(detail)) {
|
|
106
|
-
return [
|
|
107
|
-
`Could not find ${pkg.name} on the npm registry.`,
|
|
108
|
-
'Publish the package first, or update Mint from the source/release channel you installed from.'
|
|
109
|
-
].join('\n');
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return `Update failed: ${detail || 'Unknown npm error'}`;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function formatUpdateCheckError(error) {
|
|
116
|
-
const detail = [error.stderr, error.stdout, error.message].filter(Boolean).join('\n').trim();
|
|
117
|
-
if (/E404|404 Not Found|not in this registry/i.test(detail)) {
|
|
118
|
-
return [
|
|
119
|
-
`Update check unavailable: ${pkg.name} is not published on the npm registry.`,
|
|
120
|
-
'This does not mean your local Mint version is outdated.'
|
|
121
|
-
].join('\n');
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (/ENOTFOUND|ETIMEDOUT|ECONNRESET|ECONNREFUSED|network|timeout/i.test(detail)) {
|
|
125
|
-
return [
|
|
126
|
-
'Update check unavailable: npm registry could not be reached.',
|
|
127
|
-
'This does not mean your local Mint version is outdated.'
|
|
128
|
-
].join('\n');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return `Update check unavailable: ${detail || 'Unknown npm error'}`;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
async function runUpdate(options = {}) {
|
|
135
|
-
const currentVersion = pkg.version;
|
|
136
|
-
let latestVersion = '';
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
latestVersion = await getLatestVersion(pkg.name);
|
|
140
|
-
} catch (error) {
|
|
141
|
-
return {
|
|
142
|
-
status: 'error',
|
|
143
|
-
currentVersion,
|
|
144
|
-
latestVersion,
|
|
145
|
-
message: formatUpdateCheckError(error)
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (!latestVersion) {
|
|
150
|
-
return {
|
|
151
|
-
status: 'error',
|
|
152
|
-
currentVersion,
|
|
153
|
-
latestVersion: '',
|
|
154
|
-
message: 'Could not determine the latest Mint version from npm.'
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const comparison = compareVersions(currentVersion, latestVersion);
|
|
159
|
-
if (comparison >= 0) {
|
|
160
|
-
return {
|
|
161
|
-
status: 'current',
|
|
162
|
-
currentVersion,
|
|
163
|
-
latestVersion,
|
|
164
|
-
message: `Mint is already up to date (${currentVersion}).`
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (options.checkOnly) {
|
|
169
|
-
return {
|
|
170
|
-
status: 'available',
|
|
171
|
-
currentVersion,
|
|
172
|
-
latestVersion,
|
|
173
|
-
message: `Mint ${latestVersion} is available. Current version: ${currentVersion}.`
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
try {
|
|
178
|
-
await installLatest(pkg.name, { dryRun: options.dryRun });
|
|
179
|
-
return {
|
|
180
|
-
status: options.dryRun ? 'dry-run' : 'updated',
|
|
181
|
-
currentVersion,
|
|
182
|
-
latestVersion,
|
|
183
|
-
message: options.dryRun
|
|
184
|
-
? `Dry run complete. Mint would update from ${currentVersion} to ${latestVersion}.`
|
|
185
|
-
: `Mint updated from ${currentVersion} to ${latestVersion}. Restart mint to use the new version.`
|
|
186
|
-
};
|
|
187
|
-
} catch (error) {
|
|
188
|
-
return {
|
|
189
|
-
status: 'error',
|
|
190
|
-
currentVersion,
|
|
191
|
-
latestVersion,
|
|
192
|
-
message: formatUpdateError(error)
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
async function runStartupAutoUpdate(config, writeConfig, options = {}) {
|
|
198
|
-
const now = options.now || Date.now();
|
|
199
|
-
if (!shouldRunAutoUpdate(config, now)) {
|
|
200
|
-
return {
|
|
201
|
-
status: 'skipped',
|
|
202
|
-
message: 'Auto-update check skipped by cooldown.'
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const result = await runUpdate({ checkOnly: false });
|
|
207
|
-
if (typeof writeConfig === 'function') {
|
|
208
|
-
writeConfig({
|
|
209
|
-
...config,
|
|
210
|
-
lastUpdateCheckAt: new Date(now).toISOString()
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
return result;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
module.exports = {
|
|
217
|
-
compareVersions,
|
|
218
|
-
getLatestVersion,
|
|
219
|
-
installLatest,
|
|
220
|
-
normalizeNpmVersionOutput,
|
|
221
|
-
runUpdate,
|
|
222
|
-
runStartupAutoUpdate,
|
|
223
|
-
shouldRunAutoUpdate,
|
|
224
|
-
_private: {
|
|
225
|
-
parseVersion,
|
|
226
|
-
formatUpdateError,
|
|
227
|
-
formatUpdateCheckError,
|
|
228
|
-
getAutoUpdateIntervalMs
|
|
229
|
-
}
|
|
230
|
-
};
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mint Workspace Manager
|
|
3
|
-
* -----------------------
|
|
4
|
-
* Manages project-specific contexts and persistent workspaces.
|
|
5
|
-
* Stores data in ~/.config/mint/workspaces.json
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const fs = require('fs');
|
|
9
|
-
const path = require('path');
|
|
10
|
-
const os = require('os');
|
|
11
|
-
|
|
12
|
-
function getWorkspaceFile() {
|
|
13
|
-
return process.env.MINT_WORKSPACE_FILE || path.join(os.homedir(), '.config', 'mint', 'workspaces.json');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function ensureDir() {
|
|
17
|
-
const dir = path.dirname(getWorkspaceFile());
|
|
18
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function loadWorkspaces() {
|
|
22
|
-
const workspaceFile = getWorkspaceFile();
|
|
23
|
-
ensureDir();
|
|
24
|
-
if (!fs.existsSync(workspaceFile)) return {};
|
|
25
|
-
try {
|
|
26
|
-
return JSON.parse(fs.readFileSync(workspaceFile, 'utf8'));
|
|
27
|
-
} catch (e) {
|
|
28
|
-
return {};
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function saveWorkspaces(data) {
|
|
33
|
-
const workspaceFile = getWorkspaceFile();
|
|
34
|
-
ensureDir();
|
|
35
|
-
fs.writeFileSync(workspaceFile, JSON.stringify(data, null, 2));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function isPathInsideWorkspace(currentPath, workspacePath) {
|
|
39
|
-
const relative = path.relative(workspacePath, currentPath);
|
|
40
|
-
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function addWorkspace(name, rootPath, instructions = '') {
|
|
44
|
-
const workspaces = loadWorkspaces();
|
|
45
|
-
const absolutePath = path.resolve(rootPath);
|
|
46
|
-
workspaces[name] = {
|
|
47
|
-
name,
|
|
48
|
-
path: absolutePath,
|
|
49
|
-
instructions,
|
|
50
|
-
addedAt: new Date().toISOString(),
|
|
51
|
-
lastAccessed: new Date().toISOString()
|
|
52
|
-
};
|
|
53
|
-
saveWorkspaces(workspaces);
|
|
54
|
-
return workspaces[name];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function removeWorkspace(name) {
|
|
58
|
-
const workspaces = loadWorkspaces();
|
|
59
|
-
if (workspaces[name]) {
|
|
60
|
-
delete workspaces[name];
|
|
61
|
-
saveWorkspaces(workspaces);
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function getWorkspaceByPath(currentPath) {
|
|
68
|
-
const workspaces = loadWorkspaces();
|
|
69
|
-
const absoluteCurrent = path.resolve(currentPath);
|
|
70
|
-
|
|
71
|
-
// Find workspace where current path is inside or equal to workspace path
|
|
72
|
-
for (const name in workspaces) {
|
|
73
|
-
const ws = workspaces[name];
|
|
74
|
-
if (isPathInsideWorkspace(absoluteCurrent, ws.path)) {
|
|
75
|
-
return ws;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function listWorkspaces() {
|
|
82
|
-
return loadWorkspaces();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
module.exports = {
|
|
86
|
-
addWorkspace,
|
|
87
|
-
removeWorkspace,
|
|
88
|
-
getWorkspaceByPath,
|
|
89
|
-
listWorkspaces
|
|
90
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
const axios = require('axios');
|
|
2
|
-
|
|
3
|
-
class BraveSearchBridge {
|
|
4
|
-
constructor(credentials) {
|
|
5
|
-
this.apiKey = credentials.apiKey;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
async search(query) {
|
|
9
|
-
if (!this.apiKey) {
|
|
10
|
-
throw new Error('Brave Search API Key is required.');
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
const response = await axios.get('https://api.search.brave.com/res/v1/web/search', {
|
|
15
|
-
params: { q: query, count: 5 },
|
|
16
|
-
headers: {
|
|
17
|
-
'Accept': 'application/json',
|
|
18
|
-
'Accept-Encoding': 'gzip',
|
|
19
|
-
'X-Subscription-Token': this.apiKey
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
const results = response.data.web ? response.data.web.results : [];
|
|
24
|
-
return results.map(item => ({
|
|
25
|
-
title: item.title,
|
|
26
|
-
snippet: item.description,
|
|
27
|
-
link: item.url
|
|
28
|
-
}));
|
|
29
|
-
} catch (err) {
|
|
30
|
-
throw new Error(`Brave Search Failed: ${err.message}`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
module.exports = BraveSearchBridge;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { requireOptional } = require('../System/optional_require');
|
|
4
|
-
const { handleChat } = require('../AI_Brain/Gemini_API');
|
|
5
|
-
|
|
6
|
-
class DiscordBridge {
|
|
7
|
-
constructor(token) {
|
|
8
|
-
this.token = token;
|
|
9
|
-
const { Client, GatewayIntentBits, Partials } = requireOptional(
|
|
10
|
-
'discord.js',
|
|
11
|
-
'npm install discord.js'
|
|
12
|
-
);
|
|
13
|
-
this.client = new Client({
|
|
14
|
-
intents: [
|
|
15
|
-
GatewayIntentBits.Guilds,
|
|
16
|
-
GatewayIntentBits.GuildMessages,
|
|
17
|
-
GatewayIntentBits.MessageContent,
|
|
18
|
-
GatewayIntentBits.DirectMessages
|
|
19
|
-
],
|
|
20
|
-
partials: [Partials.Channel]
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async connect() {
|
|
25
|
-
this.client.on('ready', () => {
|
|
26
|
-
console.log(`[Discord Bridge] Logged in as ${this.client.user.tag}!`);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
this.client.on('messageCreate', async (message) => {
|
|
30
|
-
if (message.author.bot) return;
|
|
31
|
-
const isDM = !message.guild;
|
|
32
|
-
const isMentioned = message.mentions.has(this.client.user);
|
|
33
|
-
|
|
34
|
-
if (isDM || isMentioned) {
|
|
35
|
-
try {
|
|
36
|
-
let cleanContent = message.content;
|
|
37
|
-
if (isMentioned) {
|
|
38
|
-
cleanContent = message.content
|
|
39
|
-
.replace(`<@!${this.client.user.id}>`, '')
|
|
40
|
-
.replace(`<@${this.client.user.id}>`, '')
|
|
41
|
-
.trim();
|
|
42
|
-
}
|
|
43
|
-
if (!cleanContent) return;
|
|
44
|
-
await message.channel.sendTyping();
|
|
45
|
-
const result = await handleChat(cleanContent);
|
|
46
|
-
if (result && result.response) {
|
|
47
|
-
await message.reply(result.response);
|
|
48
|
-
}
|
|
49
|
-
} catch (err) {
|
|
50
|
-
console.error('[Discord Bridge] Error processing message:', err);
|
|
51
|
-
await message.reply('ขออภัยค่ะ เกิดข้อผิดพลาดบางอย่างในการประมวลผลข้อความ');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
await this.client.login(this.token);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async disconnect() {
|
|
60
|
-
if (this.client) {
|
|
61
|
-
await this.client.destroy();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
module.exports = DiscordBridge;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
const axios = require('axios');
|
|
2
|
-
|
|
3
|
-
class GoogleSearchBridge {
|
|
4
|
-
constructor(credentials) {
|
|
5
|
-
this.apiKey = credentials.apiKey;
|
|
6
|
-
this.cx = credentials.cx; // Custom Search Engine ID
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
async search(query) {
|
|
10
|
-
if (!this.apiKey || !this.cx) {
|
|
11
|
-
throw new Error('Google Search API Key and CX are required.');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
try {
|
|
15
|
-
const response = await axios.get('https://www.googleapis.com/customsearch/v1', {
|
|
16
|
-
params: {
|
|
17
|
-
key: this.apiKey,
|
|
18
|
-
cx: this.cx,
|
|
19
|
-
q: query,
|
|
20
|
-
num: 5
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const items = response.data.items || [];
|
|
25
|
-
return items.map(item => ({
|
|
26
|
-
title: item.title,
|
|
27
|
-
snippet: item.snippet,
|
|
28
|
-
link: item.link
|
|
29
|
-
}));
|
|
30
|
-
} catch (err) {
|
|
31
|
-
throw new Error(err.response && err.response.data && err.response.data.error
|
|
32
|
-
? `Google Search API Error: ${err.response.data.error.message}`
|
|
33
|
-
: `Google Search Failed: ${err.message}`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
module.exports = GoogleSearchBridge;
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { requireOptional } = require('../System/optional_require');
|
|
4
|
-
const { handleChat } = require('../AI_Brain/Gemini_API');
|
|
5
|
-
|
|
6
|
-
class LineBridge {
|
|
7
|
-
constructor(credentials) {
|
|
8
|
-
this._line = requireOptional('@line/bot-sdk', 'npm install @line/bot-sdk express');
|
|
9
|
-
this._express = requireOptional('express', 'npm install @line/bot-sdk express');
|
|
10
|
-
this.config = {
|
|
11
|
-
channelAccessToken: credentials.accessToken,
|
|
12
|
-
channelSecret: credentials.secret,
|
|
13
|
-
};
|
|
14
|
-
this.port = credentials.port || 3000;
|
|
15
|
-
this.client = new this._line.messagingApi.MessagingApiClient({
|
|
16
|
-
channelAccessToken: credentials.accessToken
|
|
17
|
-
});
|
|
18
|
-
this.app = this._express();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async connect() {
|
|
22
|
-
this.app.post('/callback', this._line.middleware(this.config), (req, res) => {
|
|
23
|
-
Promise
|
|
24
|
-
.all(req.body.events.map(event => this.handleEvent(event)))
|
|
25
|
-
.then((result) => res.json(result))
|
|
26
|
-
.catch((err) => {
|
|
27
|
-
console.error('[LINE Bridge] Error:', err);
|
|
28
|
-
res.status(500).end();
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
this.server = this.app.listen(this.port, () => {
|
|
33
|
-
console.log(`[LINE Bridge] Listening for webhooks on port ${this.port}`);
|
|
34
|
-
console.log(`[LINE Bridge] Webhook URL should be: <YOUR_PUBLIC_URL>/callback`);
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async handleEvent(event) {
|
|
39
|
-
if (event.type !== 'message' || event.message.type !== 'text') {
|
|
40
|
-
return Promise.resolve(null);
|
|
41
|
-
}
|
|
42
|
-
try {
|
|
43
|
-
const result = await handleChat(event.message.text);
|
|
44
|
-
if (result && result.response) {
|
|
45
|
-
return this.client.replyMessage({
|
|
46
|
-
replyToken: event.replyToken,
|
|
47
|
-
messages: [{ type: 'text', text: result.response }],
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
} catch (err) {
|
|
51
|
-
console.error('[LINE Bridge] Error processing event:', err);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async disconnect() {
|
|
56
|
-
if (this.server) this.server.close();
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
module.exports = LineBridge;
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { requireOptional } = require('../System/optional_require');
|
|
4
|
-
const { handleChat } = require('../AI_Brain/Gemini_API');
|
|
5
|
-
|
|
6
|
-
class SlackBridge {
|
|
7
|
-
constructor(credentials) {
|
|
8
|
-
const { App } = requireOptional('@slack/bolt', 'npm install @slack/bolt');
|
|
9
|
-
this.app = new App({
|
|
10
|
-
token: credentials.botToken,
|
|
11
|
-
appToken: credentials.appToken,
|
|
12
|
-
socketMode: true
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async connect() {
|
|
17
|
-
this.app.event('app_mention', async ({ event, say }) => {
|
|
18
|
-
try {
|
|
19
|
-
const text = event.text.replace(/<@.*?>/g, '').trim();
|
|
20
|
-
if (!text) return;
|
|
21
|
-
const result = await handleChat(text);
|
|
22
|
-
if (result && result.response) await say(result.response);
|
|
23
|
-
} catch (err) {
|
|
24
|
-
console.error('[Slack Bridge] Error processing app_mention:', err);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
this.app.event('message', async ({ event, say }) => {
|
|
29
|
-
if (event.channel_type === 'im') {
|
|
30
|
-
try {
|
|
31
|
-
const result = await handleChat(event.text);
|
|
32
|
-
if (result && result.response) await say(result.response);
|
|
33
|
-
} catch (err) {
|
|
34
|
-
console.error('[Slack Bridge] Error processing message:', err);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
await this.app.start();
|
|
40
|
-
console.log('[Slack Bridge] App started in Socket Mode!');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async disconnect() {
|
|
44
|
-
if (this.app) await this.app.stop();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
module.exports = SlackBridge;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { requireOptional } = require('../System/optional_require');
|
|
4
|
-
const { handleChat } = require('../AI_Brain/Gemini_API');
|
|
5
|
-
|
|
6
|
-
class TelegramBridge {
|
|
7
|
-
constructor(token) {
|
|
8
|
-
this.token = token;
|
|
9
|
-
const { Telegraf } = requireOptional('telegraf', 'npm install telegraf');
|
|
10
|
-
this.bot = new Telegraf(token);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async connect() {
|
|
14
|
-
this.bot.start((ctx) => ctx.reply('สวัสดีค่ะ! มิ้นท์พร้อมช่วยเหลือคุณใน Telegram แล้วนะคะ ✨'));
|
|
15
|
-
|
|
16
|
-
this.bot.on('text', async (ctx) => {
|
|
17
|
-
try {
|
|
18
|
-
await ctx.sendChatAction('typing');
|
|
19
|
-
const message = ctx.message.text;
|
|
20
|
-
if (!message) return;
|
|
21
|
-
const result = await handleChat(message);
|
|
22
|
-
if (result && result.response) await ctx.reply(result.response);
|
|
23
|
-
} catch (err) {
|
|
24
|
-
console.error('[Telegram Bridge] Error processing message:', err);
|
|
25
|
-
await ctx.reply('ขออภัยค่ะ เกิดข้อผิดพลาดบางอย่างในการประมวลผลข้อความ');
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
this.bot.launch();
|
|
30
|
-
console.log('[Telegram Bridge] Bot started!');
|
|
31
|
-
|
|
32
|
-
process.once('SIGINT', () => this.bot.stop('SIGINT'));
|
|
33
|
-
process.once('SIGTERM', () => this.bot.stop('SIGTERM'));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async disconnect() {
|
|
37
|
-
if (this.bot) await this.bot.stop();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
module.exports = TelegramBridge;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { requireOptional } = require('../System/optional_require');
|
|
4
|
-
const { handleChat } = require('../AI_Brain/Gemini_API');
|
|
5
|
-
|
|
6
|
-
class WhatsappBridge {
|
|
7
|
-
constructor() {
|
|
8
|
-
// Dynamic require — only loads if user has installed whatsapp-web.js
|
|
9
|
-
const { Client, LocalAuth } = requireOptional(
|
|
10
|
-
'whatsapp-web.js',
|
|
11
|
-
'npm install whatsapp-web.js qrcode-terminal'
|
|
12
|
-
);
|
|
13
|
-
this._qrcode = requireOptional('qrcode-terminal', 'npm install qrcode-terminal');
|
|
14
|
-
this.client = new Client({
|
|
15
|
-
authStrategy: new LocalAuth({
|
|
16
|
-
dataPath: require('path').join(require('os').homedir(), '.config', 'mint', 'whatsapp-session')
|
|
17
|
-
}),
|
|
18
|
-
puppeteer: {
|
|
19
|
-
args: ['--no-sandbox']
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async connect() {
|
|
25
|
-
this.client.on('qr', (qr) => {
|
|
26
|
-
console.log('[WhatsApp Bridge] Scan this QR code to login:');
|
|
27
|
-
this._qrcode.generate(qr, { small: true });
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
this.client.on('ready', () => {
|
|
31
|
-
console.log('[WhatsApp Bridge] Client is ready!');
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
this.client.on('message', async (msg) => {
|
|
35
|
-
try {
|
|
36
|
-
const chat = await msg.getChat();
|
|
37
|
-
if (chat.isGroup) return;
|
|
38
|
-
const result = await handleChat(msg.body);
|
|
39
|
-
if (result && result.response) {
|
|
40
|
-
await msg.reply(result.response);
|
|
41
|
-
}
|
|
42
|
-
} catch (err) {
|
|
43
|
-
console.error('[WhatsApp Bridge] Error processing message:', err);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
await this.client.initialize();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async disconnect() {
|
|
51
|
-
if (this.client) {
|
|
52
|
-
await this.client.destroy();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
module.exports = WhatsappBridge;
|