@emend-ai/utim 1.45.1 → 1.45.5

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.
Files changed (2) hide show
  1. package/bin/utim.js +59 -11
  2. package/package.json +1 -1
package/bin/utim.js CHANGED
@@ -78,17 +78,46 @@ function isUtimInstalled(python) {
78
78
  // ── Run pip install with given extra flags — always show output ───────────────
79
79
  function runPip(python, extraFlags) {
80
80
  try {
81
- const r = spawnSync(
82
- python,
83
- ['-m', 'pip', 'install', '--upgrade', ...extraFlags, 'utim-cli'],
84
- {
85
- stdio: 'inherit', // Always show output so errors are visible
86
- shell: isWin,
81
+ if (isWin) {
82
+ // 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 --upgrade ${extraFlags.join(' ')} utim-cli & echo ======================================== & echo Installation complete. You can close this window. & pause`;
84
+ spawnSync('cmd.exe', ['/c', 'start', '/wait', 'cmd.exe', '/c', cmdStr], {
85
+ stdio: 'ignore',
86
+ shell: true,
87
87
  windowsHide: false,
88
- timeout: 300000,
88
+ });
89
+ // After the popup window closes, verify if the pip package was actually installed
90
+ return isUtimInstalled(python);
91
+ } else if (isMac) {
92
+ // On macOS: use osascript to run it in a new Terminal window.
93
+ const lockFile = require('path').join(os.tmpdir(), `utim_install_${Date.now()}.lock`);
94
+ fs.writeFileSync(lockFile, 'running');
95
+ const installCmd = `echo "Installing UTIM Python engine..."; "${python}" -m pip install --upgrade ${extraFlags.join(' ')} utim-cli; rm -f "${lockFile}"; exit`;
96
+ const osaScript = `tell application "Terminal" to do script "${installCmd.replace(/"/g, '\\"')}"`;
97
+
98
+ spawnSync('osascript', ['-e', osaScript], { stdio: 'ignore' });
99
+
100
+ // Poll for lockfile deletion (timeout after 5 minutes)
101
+ let elapsed = 0;
102
+ while (fs.existsSync(lockFile) && elapsed < 300) {
103
+ spawnSync('sleep', ['1']);
104
+ elapsed++;
89
105
  }
90
- );
91
- return r.status === 0;
106
+ try { fs.unlinkSync(lockFile); } catch (_) {}
107
+ return isUtimInstalled(python);
108
+ } else {
109
+ // Linux / Termux fallback: run in current terminal
110
+ const r = spawnSync(
111
+ python,
112
+ ['-m', 'pip', 'install', '--upgrade', ...extraFlags, 'utim-cli'],
113
+ {
114
+ stdio: 'inherit',
115
+ shell: false,
116
+ timeout: 300000,
117
+ }
118
+ );
119
+ return r.status === 0;
120
+ }
92
121
  } catch (_) {
93
122
  return false;
94
123
  }
@@ -99,12 +128,31 @@ function installEngine(python) {
99
128
  // Termux: install prebuilt system packages first to skip pydantic-core compilation
100
129
  if (isTermux) {
101
130
  process.stderr.write(
102
- '\n💡 Termux: installing prebuilt system dependencies first...\n\n'
131
+ '\n💡 Termux: adding Termux User Repository (tur-repo) to find prebuilt python-pydantic...\n\n'
103
132
  );
104
- spawnSync('pkg', ['install', '-y', 'python-cryptography', 'python-pydantic'], {
133
+ // Register tur-repo first (contains prebuilt python-pydantic)
134
+ spawnSync('pkg', ['install', '-y', 'tur-repo'], { stdio: 'inherit', shell: false });
135
+
136
+ process.stderr.write(
137
+ '\n💡 Termux: installing prebuilt system cryptography and pydantic packages...\n\n'
138
+ );
139
+ const r1 = spawnSync('pkg', ['install', '-y', 'python-cryptography', 'python-pydantic'], {
105
140
  stdio: 'inherit',
106
141
  shell: false,
107
142
  });
143
+
144
+ // Fallback: If prebuilt system packages fail to install, install Rust compiler toolchain
145
+ // so pip can compile pydantic-core and cryptography from source
146
+ if (r1.status !== 0) {
147
+ process.stderr.write(
148
+ '\n💡 Prebuilt package setup failed. Installing build dependencies (rust, clang) to compile from source...\n\n'
149
+ );
150
+ spawnSync('pkg', ['install', '-y', 'clang', 'rust', 'make', 'libfft-dev', 'libffi-dev', 'openssl-dev'], {
151
+ stdio: 'inherit',
152
+ shell: false,
153
+ });
154
+ }
155
+
108
156
  spawnSync(python, ['-m', 'pip', 'install', '--upgrade', 'pip', 'setuptools', 'wheel'], {
109
157
  stdio: 'pipe',
110
158
  shell: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emend-ai/utim",
3
- "version": "1.45.1",
3
+ "version": "1.45.5",
4
4
  "description": "UTIM – Universal Terminal Intelligence Manager. An agentic AI coding assistant for your terminal.",
5
5
  "keywords": [
6
6
  "ai",