@emend-ai/utim 1.43.3 → 1.43.6
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/bin/utim.js +92 -38
- package/package.json +44 -44
package/bin/utim.js
CHANGED
|
@@ -6,13 +6,24 @@ const os = require('os');
|
|
|
6
6
|
const fs = require('fs');
|
|
7
7
|
|
|
8
8
|
const args = process.argv.slice(2);
|
|
9
|
-
const
|
|
9
|
+
const isWin = os.platform() === 'win32';
|
|
10
|
+
const isTermux =
|
|
11
|
+
(process.env.PREFIX && process.env.PREFIX.includes('com.termux')) ||
|
|
12
|
+
fs.existsSync('/data/data/com.termux');
|
|
10
13
|
|
|
11
14
|
// ── Find a working Python 3 interpreter ──────────────────────────────────────
|
|
12
15
|
function findPython() {
|
|
13
|
-
|
|
16
|
+
const candidates = isWin
|
|
17
|
+
? ['python', 'python3', 'py']
|
|
18
|
+
: ['python3', 'python'];
|
|
19
|
+
|
|
20
|
+
for (const candidate of candidates) {
|
|
14
21
|
try {
|
|
15
|
-
const r = spawnSync(candidate, ['--version'], {
|
|
22
|
+
const r = spawnSync(candidate, ['--version'], {
|
|
23
|
+
encoding: 'utf8',
|
|
24
|
+
timeout: 4000,
|
|
25
|
+
shell: isWin,
|
|
26
|
+
});
|
|
16
27
|
const out = (r.stdout || '') + (r.stderr || '');
|
|
17
28
|
if (out.includes('Python 3')) return candidate;
|
|
18
29
|
} catch (_) {}
|
|
@@ -20,51 +31,83 @@ function findPython() {
|
|
|
20
31
|
return null;
|
|
21
32
|
}
|
|
22
33
|
|
|
23
|
-
// ──
|
|
24
|
-
function
|
|
34
|
+
// ── Check if a binary is actually available and runnable ─────────────────────
|
|
35
|
+
function commandExists(cmd) {
|
|
25
36
|
try {
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} catch (_) {
|
|
35
|
-
|
|
37
|
+
// Use 'where' on Windows, 'which' on Unix to check existence
|
|
38
|
+
const checker = isWin ? 'where' : 'which';
|
|
39
|
+
const probe = spawnSync(checker, [cmd], {
|
|
40
|
+
encoding: 'utf8',
|
|
41
|
+
timeout: 3000,
|
|
42
|
+
shell: false,
|
|
43
|
+
});
|
|
44
|
+
return probe.status === 0 && (probe.stdout || '').trim().length > 0;
|
|
45
|
+
} catch (_) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ── Launch a command, forwarding stdio ───────────────────────────────────────
|
|
51
|
+
function launch(cmd, launchArgs) {
|
|
52
|
+
const proc = spawn(cmd, launchArgs, {
|
|
53
|
+
stdio: 'inherit',
|
|
54
|
+
shell: isWin,
|
|
55
|
+
});
|
|
56
|
+
proc.on('exit', (code) => process.exit(code == null ? 0 : code));
|
|
57
|
+
proc.on('error', () => {
|
|
58
|
+
// If spawning fails at OS level, fall through (caller handles)
|
|
59
|
+
});
|
|
60
|
+
return true;
|
|
36
61
|
}
|
|
37
62
|
|
|
38
63
|
// ── Try the installed console_script entry point ──────────────────────────────
|
|
39
64
|
function tryEntryPoint() {
|
|
40
|
-
|
|
65
|
+
// Explicitly verify the binary exists before attempting to spawn it.
|
|
66
|
+
// This prevents the "not recognised as internal or external command" error
|
|
67
|
+
// from surfacing to the user when pip install was skipped.
|
|
68
|
+
if (!commandExists('utim-agent-core')) return false;
|
|
69
|
+
return launch('utim-agent-core', args);
|
|
41
70
|
}
|
|
42
71
|
|
|
43
72
|
// ── Try via `python -m utim_cli.utim` ───────────────────────────────────────
|
|
44
73
|
function tryModule(python) {
|
|
45
74
|
try {
|
|
46
|
-
const probe = spawnSync(
|
|
75
|
+
const probe = spawnSync(
|
|
76
|
+
python,
|
|
77
|
+
['-c', 'import utim_cli'],
|
|
78
|
+
{ shell: isWin, timeout: 5000 }
|
|
79
|
+
);
|
|
47
80
|
if (probe.status === 0) {
|
|
48
|
-
|
|
49
|
-
proc.on('exit', (code) => process.exit(code == null ? 0 : code));
|
|
50
|
-
return true;
|
|
81
|
+
return launch(python, ['-m', 'utim_cli.utim', ...args]);
|
|
51
82
|
}
|
|
52
83
|
} catch (_) {}
|
|
53
84
|
return false;
|
|
54
85
|
}
|
|
55
86
|
|
|
56
|
-
// ──
|
|
87
|
+
// ── Install from PyPI then retry ─────────────────────────────────────────────
|
|
57
88
|
function selfInstallAndRun(python) {
|
|
58
|
-
console.error('\n⚙ First run: installing UTIM Python engine from PyPI
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
89
|
+
console.error('\n⚙ First run: installing UTIM Python engine from PyPI...\n');
|
|
90
|
+
|
|
91
|
+
// On Termux, prebuilt packages must be installed first
|
|
92
|
+
if (isTermux) {
|
|
93
|
+
console.error(
|
|
94
|
+
'💡 Termux detected. Installing prebuilt dependencies first...\n' +
|
|
95
|
+
' Run these commands if install fails:\n' +
|
|
96
|
+
' pkg install python-cryptography python-pydantic\n' +
|
|
97
|
+
' pip install utim-cli\n'
|
|
98
|
+
);
|
|
66
99
|
}
|
|
67
|
-
|
|
100
|
+
|
|
101
|
+
const install = spawnSync(
|
|
102
|
+
python,
|
|
103
|
+
['-m', 'pip', 'install', '--upgrade', 'utim-cli'],
|
|
104
|
+
{ stdio: 'inherit', shell: isWin }
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
if (install.status !== 0) return false;
|
|
108
|
+
|
|
109
|
+
// Retry both paths after install
|
|
110
|
+
return tryEntryPoint() || tryModule(python);
|
|
68
111
|
}
|
|
69
112
|
|
|
70
113
|
// ── Main ─────────────────────────────────────────────────────────────────────
|
|
@@ -76,17 +119,28 @@ const ok =
|
|
|
76
119
|
(python && selfInstallAndRun(python));
|
|
77
120
|
|
|
78
121
|
if (!ok) {
|
|
79
|
-
console.error('\
|
|
80
|
-
const isTermux = (process.env.PREFIX && process.env.PREFIX.includes('com.termux')) || fs.existsSync('/data/data/com.termux');
|
|
122
|
+
console.error('\n❌ UTIM Engine could not start.\n');
|
|
81
123
|
if (isTermux) {
|
|
82
|
-
console.error(
|
|
83
|
-
|
|
84
|
-
|
|
124
|
+
console.error(
|
|
125
|
+
'💡 Termux: Prebuilt packages are required to avoid compilation errors.\n' +
|
|
126
|
+
' Run:\n' +
|
|
127
|
+
' pkg install python-cryptography python-pydantic\n' +
|
|
128
|
+
' pip install utim-cli\n'
|
|
129
|
+
);
|
|
85
130
|
} else if (!python) {
|
|
86
|
-
console.error(
|
|
131
|
+
console.error(
|
|
132
|
+
'Python 3 was not found on this system.\n' +
|
|
133
|
+
'Please install Python 3.9+ from https://python.org\n' +
|
|
134
|
+
'Then run: pip install utim-cli\n'
|
|
135
|
+
);
|
|
87
136
|
} else {
|
|
88
|
-
console.error(
|
|
89
|
-
|
|
137
|
+
console.error(
|
|
138
|
+
`Python found at: ${python}\n` +
|
|
139
|
+
'The UTIM Python engine is not installed. Please run:\n' +
|
|
140
|
+
' pip install utim-cli\n' +
|
|
141
|
+
'or:\n' +
|
|
142
|
+
' pip3 install --upgrade utim-cli\n'
|
|
143
|
+
);
|
|
90
144
|
}
|
|
91
145
|
process.exit(1);
|
|
92
146
|
}
|
package/package.json
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@emend-ai/utim",
|
|
3
|
-
"version": "1.43.
|
|
4
|
-
"description": "UTIM – Universal Terminal Intelligence Manager. An agentic AI coding assistant for your terminal.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"ai",
|
|
7
|
-
"agent",
|
|
8
|
-
"cli",
|
|
9
|
-
"coding-assistant",
|
|
10
|
-
"agentic",
|
|
11
|
-
"llm",
|
|
12
|
-
"mcp",
|
|
13
|
-
"utim"
|
|
14
|
-
],
|
|
15
|
-
"homepage": "https://utim.
|
|
16
|
-
"bugs": {
|
|
17
|
-
"url": "https://github.com/emendai/utim/issues"
|
|
18
|
-
},
|
|
19
|
-
"repository": {
|
|
20
|
-
"type": "git",
|
|
21
|
-
"url": "https://github.com/emendai/utim.git"
|
|
22
|
-
},
|
|
23
|
-
"license": "MIT",
|
|
24
|
-
"author": "Emendai <support@emendai.com>",
|
|
25
|
-
"bin": {
|
|
26
|
-
"utim": "bin/utim.js"
|
|
27
|
-
},
|
|
28
|
-
"scripts": {
|
|
29
|
-
"postinstall": "node scripts/postinstall.js"
|
|
30
|
-
},
|
|
31
|
-
"files": [
|
|
32
|
-
"bin/utim.js",
|
|
33
|
-
"scripts/postinstall.js",
|
|
34
|
-
"README.md",
|
|
35
|
-
"LICENSE"
|
|
36
|
-
],
|
|
37
|
-
"engines": {
|
|
38
|
-
"node": ">=16.0.0"
|
|
39
|
-
},
|
|
40
|
-
"publishConfig": {
|
|
41
|
-
"access": "public",
|
|
42
|
-
"registry": "https://registry.npmjs.org/"
|
|
43
|
-
}
|
|
44
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@emend-ai/utim",
|
|
3
|
+
"version": "1.43.6",
|
|
4
|
+
"description": "UTIM – Universal Terminal Intelligence Manager. An agentic AI coding assistant for your terminal.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"agent",
|
|
8
|
+
"cli",
|
|
9
|
+
"coding-assistant",
|
|
10
|
+
"agentic",
|
|
11
|
+
"llm",
|
|
12
|
+
"mcp",
|
|
13
|
+
"utim"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://utim.dev",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/emendai/utim/issues"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/emendai/utim.git"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"author": "Emendai <support@emendai.com>",
|
|
25
|
+
"bin": {
|
|
26
|
+
"utim": "bin/utim.js"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"postinstall": "node scripts/postinstall.js"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"bin/utim.js",
|
|
33
|
+
"scripts/postinstall.js",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=16.0.0"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public",
|
|
42
|
+
"registry": "https://registry.npmjs.org/"
|
|
43
|
+
}
|
|
44
|
+
}
|