terminator-mcp-agent 0.23.35 → 0.23.43
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/package.json +9 -7
- package/scripts/download-source.js +207 -0
package/package.json
CHANGED
|
@@ -12,25 +12,27 @@
|
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"index.js",
|
|
15
|
-
"config.js"
|
|
15
|
+
"config.js",
|
|
16
|
+
"scripts/download-source.js"
|
|
16
17
|
],
|
|
17
18
|
"name": "terminator-mcp-agent",
|
|
18
19
|
"optionalDependencies": {
|
|
19
|
-
"terminator-mcp-darwin-arm64": "0.23.
|
|
20
|
-
"terminator-mcp-darwin-x64": "0.23.
|
|
21
|
-
"terminator-mcp-linux-x64-gnu": "0.23.
|
|
22
|
-
"terminator-mcp-win32-arm64-msvc": "0.23.
|
|
23
|
-
"terminator-mcp-win32-x64-msvc": "0.23.
|
|
20
|
+
"terminator-mcp-darwin-arm64": "0.23.43",
|
|
21
|
+
"terminator-mcp-darwin-x64": "0.23.43",
|
|
22
|
+
"terminator-mcp-linux-x64-gnu": "0.23.43",
|
|
23
|
+
"terminator-mcp-win32-arm64-msvc": "0.23.43",
|
|
24
|
+
"terminator-mcp-win32-x64-msvc": "0.23.43"
|
|
24
25
|
},
|
|
25
26
|
"repository": {
|
|
26
27
|
"type": "git",
|
|
27
28
|
"url": "https://github.com/mediar-ai/terminator"
|
|
28
29
|
},
|
|
29
30
|
"scripts": {
|
|
31
|
+
"postinstall": "node ./scripts/download-source.js",
|
|
30
32
|
"build": "node ./utils/build-server.js --release",
|
|
31
33
|
"build:debug": "node ./utils/build-server.js --debug",
|
|
32
34
|
"sync-version": "node ./utils/sync-version.js",
|
|
33
35
|
"update-badges": "node ./utils/update-badges.js"
|
|
34
36
|
},
|
|
35
|
-
"version": "0.23.
|
|
37
|
+
"version": "0.23.43"
|
|
36
38
|
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
|
|
9
|
+
// Get platform-specific app data directory
|
|
10
|
+
function getAppDataDir() {
|
|
11
|
+
switch (process.platform) {
|
|
12
|
+
case 'win32':
|
|
13
|
+
return process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
|
|
14
|
+
case 'darwin':
|
|
15
|
+
return path.join(os.homedir(), 'Library', 'Application Support');
|
|
16
|
+
default: // linux and others
|
|
17
|
+
return process.env.XDG_DATA_HOME || path.join(os.homedir(), '.local', 'share');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const MEDIAR_DIR = path.join(getAppDataDir(), 'mediar');
|
|
22
|
+
const SOURCE_DIR = path.join(MEDIAR_DIR, 'terminator-source');
|
|
23
|
+
const MARKER_FILE = path.join(SOURCE_DIR, '.terminator-source-meta.json');
|
|
24
|
+
const REPO = 'mediar-ai/terminator';
|
|
25
|
+
|
|
26
|
+
// Simple fetch using https module (no dependencies)
|
|
27
|
+
function fetch(url) {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
const request = https.get(url, {
|
|
30
|
+
headers: { 'User-Agent': 'terminator-mcp-agent' }
|
|
31
|
+
}, (response) => {
|
|
32
|
+
// Handle redirects
|
|
33
|
+
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
|
|
34
|
+
return fetch(response.headers.location).then(resolve).catch(reject);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (response.statusCode !== 200) {
|
|
38
|
+
reject(new Error(`HTTP ${response.statusCode}`));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let data = '';
|
|
43
|
+
response.on('data', chunk => data += chunk);
|
|
44
|
+
response.on('end', () => resolve({ data, headers: response.headers }));
|
|
45
|
+
});
|
|
46
|
+
request.on('error', reject);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Download file to disk
|
|
51
|
+
function downloadFile(url, destPath) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const file = fs.createWriteStream(destPath);
|
|
54
|
+
|
|
55
|
+
const request = https.get(url, {
|
|
56
|
+
headers: { 'User-Agent': 'terminator-mcp-agent' }
|
|
57
|
+
}, (response) => {
|
|
58
|
+
// Handle redirects
|
|
59
|
+
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
|
|
60
|
+
file.close();
|
|
61
|
+
fs.unlinkSync(destPath);
|
|
62
|
+
return downloadFile(response.headers.location, destPath).then(resolve).catch(reject);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (response.statusCode !== 200) {
|
|
66
|
+
file.close();
|
|
67
|
+
fs.unlinkSync(destPath);
|
|
68
|
+
reject(new Error(`HTTP ${response.statusCode}`));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
response.pipe(file);
|
|
73
|
+
file.on('finish', () => {
|
|
74
|
+
file.close();
|
|
75
|
+
resolve();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
request.on('error', (err) => {
|
|
80
|
+
file.close();
|
|
81
|
+
fs.unlinkSync(destPath);
|
|
82
|
+
reject(err);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function getLatestRelease() {
|
|
88
|
+
const { data } = await fetch(`https://api.github.com/repos/${REPO}/releases/latest`);
|
|
89
|
+
const release = JSON.parse(data);
|
|
90
|
+
return {
|
|
91
|
+
tag: release.tag_name,
|
|
92
|
+
zipUrl: release.zipball_url
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function needsUpdate() {
|
|
97
|
+
if (!fs.existsSync(SOURCE_DIR) || !fs.existsSync(MARKER_FILE)) {
|
|
98
|
+
return { needed: true, reason: 'not installed' };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
const meta = JSON.parse(fs.readFileSync(MARKER_FILE, 'utf8'));
|
|
103
|
+
const hoursSince = (Date.now() - new Date(meta.updated).getTime()) / (1000 * 60 * 60);
|
|
104
|
+
|
|
105
|
+
if (hoursSince > 24) {
|
|
106
|
+
return { needed: true, reason: 'older than 24h', currentTag: meta.tag };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return { needed: false, tag: meta.tag };
|
|
110
|
+
} catch {
|
|
111
|
+
return { needed: true, reason: 'invalid metadata' };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function downloadAndExtract(zipUrl, tag) {
|
|
116
|
+
// Ensure mediar directory exists
|
|
117
|
+
if (!fs.existsSync(MEDIAR_DIR)) {
|
|
118
|
+
fs.mkdirSync(MEDIAR_DIR, { recursive: true });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const zipPath = path.join(MEDIAR_DIR, 'terminator-source.zip');
|
|
122
|
+
const tempExtractDir = path.join(MEDIAR_DIR, 'terminator-source-temp');
|
|
123
|
+
|
|
124
|
+
console.error(`Downloading terminator source (${tag})...`);
|
|
125
|
+
await downloadFile(zipUrl, zipPath);
|
|
126
|
+
|
|
127
|
+
console.error('Extracting...');
|
|
128
|
+
|
|
129
|
+
// Clean up temp dir if exists
|
|
130
|
+
if (fs.existsSync(tempExtractDir)) {
|
|
131
|
+
fs.rmSync(tempExtractDir, { recursive: true, force: true });
|
|
132
|
+
}
|
|
133
|
+
fs.mkdirSync(tempExtractDir, { recursive: true });
|
|
134
|
+
|
|
135
|
+
// Extract zip
|
|
136
|
+
try {
|
|
137
|
+
if (process.platform === 'win32') {
|
|
138
|
+
execSync(`powershell -Command "Expand-Archive -Path '${zipPath}' -DestinationPath '${tempExtractDir}' -Force"`, { stdio: 'pipe' });
|
|
139
|
+
} else {
|
|
140
|
+
execSync(`unzip -q "${zipPath}" -d "${tempExtractDir}"`, { stdio: 'pipe' });
|
|
141
|
+
}
|
|
142
|
+
} catch (err) {
|
|
143
|
+
throw new Error(`Failed to extract: ${err.message}`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Find extracted folder (mediar-ai-terminator-<hash>)
|
|
147
|
+
const extracted = fs.readdirSync(tempExtractDir).find(f => f.startsWith('mediar-ai-terminator-'));
|
|
148
|
+
if (!extracted) {
|
|
149
|
+
throw new Error('Could not find extracted folder');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Remove old source dir and rename extracted
|
|
153
|
+
if (fs.existsSync(SOURCE_DIR)) {
|
|
154
|
+
fs.rmSync(SOURCE_DIR, { recursive: true, force: true });
|
|
155
|
+
}
|
|
156
|
+
fs.renameSync(path.join(tempExtractDir, extracted), SOURCE_DIR);
|
|
157
|
+
|
|
158
|
+
// Cleanup
|
|
159
|
+
fs.rmSync(tempExtractDir, { recursive: true, force: true });
|
|
160
|
+
fs.unlinkSync(zipPath);
|
|
161
|
+
|
|
162
|
+
// Write metadata
|
|
163
|
+
fs.writeFileSync(MARKER_FILE, JSON.stringify({
|
|
164
|
+
tag,
|
|
165
|
+
updated: new Date().toISOString(),
|
|
166
|
+
source: 'github-release'
|
|
167
|
+
}, null, 2));
|
|
168
|
+
|
|
169
|
+
console.error(`Terminator source ${tag} installed to ${SOURCE_DIR}`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function main() {
|
|
173
|
+
try {
|
|
174
|
+
const check = needsUpdate();
|
|
175
|
+
|
|
176
|
+
if (!check.needed) {
|
|
177
|
+
console.error(`Terminator source ${check.tag} is up to date`);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
console.error(`Terminator source update needed: ${check.reason}`);
|
|
182
|
+
|
|
183
|
+
const { tag, zipUrl } = await getLatestRelease();
|
|
184
|
+
|
|
185
|
+
// Skip if same version (just update timestamp)
|
|
186
|
+
if (check.currentTag === tag) {
|
|
187
|
+
console.error(`Already have ${tag}, updating timestamp`);
|
|
188
|
+
const meta = JSON.parse(fs.readFileSync(MARKER_FILE, 'utf8'));
|
|
189
|
+
meta.updated = new Date().toISOString();
|
|
190
|
+
fs.writeFileSync(MARKER_FILE, JSON.stringify(meta, null, 2));
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
await downloadAndExtract(zipUrl, tag);
|
|
195
|
+
} catch (err) {
|
|
196
|
+
// Non-fatal - MCP agent can still work without search tools
|
|
197
|
+
console.error(`Warning: Failed to download terminator source: ${err.message}`);
|
|
198
|
+
console.error('Search tools will not be available until source is downloaded.');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Run if called directly
|
|
203
|
+
if (require.main === module) {
|
|
204
|
+
main();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
module.exports = { main, needsUpdate, getAppDataDir, SOURCE_DIR };
|