@emend-ai/utim 1.46.28 → 1.46.31
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/README.md +38 -1
- package/bin/utim.js +26 -6
- package/package.json +2 -2
- package/scripts/postinstall.js +13 -1
package/README.md
CHANGED
|
@@ -119,6 +119,43 @@ Inside the interactive chat terminal, type these slash commands for direct works
|
|
|
119
119
|
## 📄 Related Documentation
|
|
120
120
|
|
|
121
121
|
- [📖 Full Documentation](https://utim.dev/docs)
|
|
122
|
-
- [🔒 Security Policy](SECURITY.md)
|
|
122
|
+
- [🔒 Security Policy](SECURITY.md) — vulnerability reporting, security@utim.dev
|
|
123
|
+
- [🗄️ Data Handling Reference](DATA_HANDLING.md) — what stays local, what goes to backend, what goes to model providers
|
|
123
124
|
- [📊 SLA & Support](SLA.md)
|
|
124
125
|
- [🛡️ Privacy Policy](landing/src/docs_md/privacy.md)
|
|
126
|
+
|
|
127
|
+
## 📦 Installation Methods
|
|
128
|
+
|
|
129
|
+
### npm (recommended — works without Python pre-installed)
|
|
130
|
+
```bash
|
|
131
|
+
npm install -g @emend-ai/utim
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### pip (from PyPI)
|
|
135
|
+
```bash
|
|
136
|
+
pip install utim-cli
|
|
137
|
+
# Full install with optional features (web search, images, parsers)
|
|
138
|
+
pip install "utim-cli[full]"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Source install (development)
|
|
142
|
+
```bash
|
|
143
|
+
git clone https://github.com/emendai/utim.git
|
|
144
|
+
cd utim
|
|
145
|
+
pip install -e ".[full]"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Smoke-test your install
|
|
149
|
+
```bash
|
|
150
|
+
utim --version # Should print the current version
|
|
151
|
+
utim doctor # Runs diagnostics — all checks should pass
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
See [INSTALLATION_VERIFICATION.md](INSTALLATION_VERIFICATION.md) for detailed verification steps and troubleshooting.
|
|
155
|
+
|
|
156
|
+
## 🔢 Version
|
|
157
|
+
|
|
158
|
+
UTIM uses a single canonical version defined in [`utim_cli/_version.py`](utim_cli/_version.py).
|
|
159
|
+
Run `python scripts/sync_version.py` to propagate a version bump to all surfaces
|
|
160
|
+
(`package.json`, `pyproject.toml`, `CHANGELOG.md`) before releasing.
|
|
161
|
+
|
package/bin/utim.js
CHANGED
|
@@ -18,6 +18,17 @@ const isTermux =
|
|
|
18
18
|
(process.env.PREFIX && process.env.PREFIX.includes('com.termux')) ||
|
|
19
19
|
fs.existsSync('/data/data/com.termux');
|
|
20
20
|
|
|
21
|
+
const path = require('path');
|
|
22
|
+
let versionPin = '';
|
|
23
|
+
try {
|
|
24
|
+
const pkg = require(path.join(__dirname, '..', 'package.json'));
|
|
25
|
+
if (pkg.version) {
|
|
26
|
+
versionPin = `==${pkg.version}`;
|
|
27
|
+
}
|
|
28
|
+
} catch (_) {}
|
|
29
|
+
|
|
30
|
+
const pipPackage = `utim-cli${versionPin}`;
|
|
31
|
+
|
|
21
32
|
// ── Spinner (no-op when not a TTY) ───────────────────────────────────────────
|
|
22
33
|
function createSpinner(text) {
|
|
23
34
|
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
@@ -69,7 +80,18 @@ function isUtimInstalled(python) {
|
|
|
69
80
|
shell: isWin,
|
|
70
81
|
windowsHide: true,
|
|
71
82
|
});
|
|
72
|
-
|
|
83
|
+
if (r.status !== 0) return false;
|
|
84
|
+
|
|
85
|
+
// Enforce that installed version matches expectedVersion
|
|
86
|
+
if (versionPin) {
|
|
87
|
+
const expectedVersion = versionPin.replace('==', '').trim();
|
|
88
|
+
const stdoutStr = r.stdout || '';
|
|
89
|
+
const match = stdoutStr.match(/^Version:\s*([^\r\n]+)/m);
|
|
90
|
+
if (match && match[1].trim() !== expectedVersion) {
|
|
91
|
+
return false; // version mismatch, force update/reinstall
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return (r.stdout || '').includes('Name:');
|
|
73
95
|
} catch (_) {
|
|
74
96
|
return false;
|
|
75
97
|
}
|
|
@@ -80,7 +102,7 @@ function runPip(python, extraFlags) {
|
|
|
80
102
|
try {
|
|
81
103
|
if (isWin) {
|
|
82
104
|
// On Windows: spawn in a new Command Prompt window and block until it is closed.
|
|
83
|
-
const cmdStr = `title UTIM Setup & echo ======================================== & echo Installing UTIM Python engine and dependencies... & echo ======================================== & "${python}" -m pip install
|
|
105
|
+
const cmdStr = `title UTIM Setup & echo ======================================== & echo Installing UTIM Python engine and dependencies... & echo ======================================== & "${python}" -m pip install ${extraFlags.join(' ')} ${pipPackage} & echo ======================================== & echo Installation complete. You can close this window. & pause`;
|
|
84
106
|
spawnSync('cmd.exe', ['/c', 'start', '/wait', 'cmd.exe', '/c', cmdStr], {
|
|
85
107
|
stdio: 'ignore',
|
|
86
108
|
shell: true,
|
|
@@ -92,7 +114,7 @@ function runPip(python, extraFlags) {
|
|
|
92
114
|
// On macOS: use osascript to run it in a new Terminal window.
|
|
93
115
|
const lockFile = require('path').join(os.tmpdir(), `utim_install_${Date.now()}.lock`);
|
|
94
116
|
fs.writeFileSync(lockFile, 'running');
|
|
95
|
-
const installCmd = `echo "Installing UTIM Python engine..."; "${python}" -m pip install
|
|
117
|
+
const installCmd = `echo "Installing UTIM Python engine..."; "${python}" -m pip install ${extraFlags.join(' ')} ${pipPackage}; rm -f "${lockFile}"; exit`;
|
|
96
118
|
const osaScript = `tell application "Terminal" to do script "${installCmd.replace(/"/g, '\\"')}"`;
|
|
97
119
|
|
|
98
120
|
spawnSync('osascript', ['-e', osaScript], { stdio: 'ignore' });
|
|
@@ -113,10 +135,8 @@ function runPip(python, extraFlags) {
|
|
|
113
135
|
// versions of pydantic-core from PyPI and trying to compile from source.
|
|
114
136
|
// Instead, use --upgrade-strategy only-if-needed to keep the pre-compiled version.
|
|
115
137
|
pipArgs.push('--upgrade-strategy', 'only-if-needed');
|
|
116
|
-
} else {
|
|
117
|
-
pipArgs.push('--upgrade');
|
|
118
138
|
}
|
|
119
|
-
pipArgs.push(...extraFlags,
|
|
139
|
+
pipArgs.push(...extraFlags, pipPackage);
|
|
120
140
|
|
|
121
141
|
const r = spawnSync(python, pipArgs, {
|
|
122
142
|
stdio: 'inherit',
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@emend-ai/utim",
|
|
3
|
-
"version": "1.46.
|
|
4
|
-
"description": "UTIM
|
|
3
|
+
"version": "1.46.31",
|
|
4
|
+
"description": "UTIM \u2013 Universal Terminal Intelligence Manager. An agentic AI coding assistant for your terminal.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
7
7
|
"agent",
|
package/scripts/postinstall.js
CHANGED
|
@@ -58,13 +58,25 @@ if (!python) {
|
|
|
58
58
|
process.exit(0);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// Read the version from package.json to pin the python engine version
|
|
62
|
+
const path = require('path');
|
|
63
|
+
let versionPin = '';
|
|
64
|
+
try {
|
|
65
|
+
const pkg = require(path.join(__dirname, '..', 'package.json'));
|
|
66
|
+
if (pkg.version) {
|
|
67
|
+
versionPin = `==${pkg.version}`;
|
|
68
|
+
}
|
|
69
|
+
} catch (_) {}
|
|
70
|
+
|
|
71
|
+
const pipPackage = `utim-cli${versionPin}`;
|
|
72
|
+
|
|
61
73
|
// Silently pre-install in the background (pipe output, not inherit)
|
|
62
74
|
// so the npm install output stays clean. Any failure is fine —
|
|
63
75
|
// the launcher self-heals on first `utim` run.
|
|
64
76
|
try {
|
|
65
77
|
const r = spawnSync(
|
|
66
78
|
python,
|
|
67
|
-
['-m', 'pip', 'install', '--
|
|
79
|
+
['-m', 'pip', 'install', '--quiet', pipPackage],
|
|
68
80
|
{
|
|
69
81
|
stdio: 'pipe',
|
|
70
82
|
shell: isWin,
|