@nghyane/arcane 0.1.22 → 0.1.23

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/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.1.23] - 2026-03-08
6
+
7
+ ### Fixed
8
+
9
+ - Fix Python setup installing packages into system Python instead of managed venv, causing "kernel unavailable" even after install
10
+ - Fix missing `ensurepip` step when managed venv lacks pip
11
+ - Fix misleading error message to point users to `arcane setup python`
12
+
5
13
  ## [0.1.22] - 2026-03-08
6
14
 
7
15
  ### Changed
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@nghyane/arcane",
4
- "version": "0.1.22",
4
+ "version": "0.1.23",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/nghyane/arcane",
7
7
  "author": "Can Bölük",
@@ -160,7 +160,18 @@ async function installPythonPackages(
160
160
  pythonPath: string,
161
161
  uvPath?: string,
162
162
  pipPath?: string,
163
+ usingManagedEnv?: boolean,
163
164
  ): Promise<{ success: boolean; usedManagedEnv: boolean }> {
165
+ const managedPython = managedPythonPath();
166
+ const hasManagedEnv = await Bun.file(managedPython).exists();
167
+
168
+ // If the managed venv already exists, install directly into it.
169
+ // resolvePythonRuntime prefers managed venv over system Python,
170
+ // so installing into system Python would be invisible to the check.
171
+ if (hasManagedEnv || usingManagedEnv) {
172
+ return installIntoManagedEnv(packages, pythonPath, uvPath);
173
+ }
174
+
164
175
  if (uvPath) {
165
176
  console.log(chalk.dim(`Installing via uv: ${packages.join(" ")}`));
166
177
  const result = await $`${uvPath} pip install ${packages}`.nothrow();
@@ -178,24 +189,35 @@ async function installPythonPackages(
178
189
  }
179
190
 
180
191
  console.log(chalk.dim(`Falling back to managed virtual environment: ${MANAGED_PYTHON_ENV}`));
192
+ return installIntoManagedEnv(packages, pythonPath, uvPath);
193
+ }
194
+
195
+ async function installIntoManagedEnv(
196
+ packages: string[],
197
+ pythonPath: string,
198
+ uvPath?: string,
199
+ ): Promise<{ success: boolean; usedManagedEnv: boolean }> {
200
+ console.log(chalk.dim(`Installing into managed environment: ${MANAGED_PYTHON_ENV}`));
181
201
 
182
202
  if (uvPath) {
183
- const createEnv = await $`${uvPath} venv ${MANAGED_PYTHON_ENV}`.quiet().nothrow();
203
+ // Ensure venv exists (no-op if already created)
204
+ await $`${uvPath} venv ${MANAGED_PYTHON_ENV}`.quiet().nothrow();
205
+ const result = await $`${uvPath} pip install --python ${MANAGED_PYTHON_ENV} ${packages}`.nothrow();
206
+ return { success: result.exitCode === 0, usedManagedEnv: true };
207
+ }
208
+
209
+ const managedPython = managedPythonPath();
210
+ if (!(await Bun.file(managedPython).exists())) {
211
+ const createEnv = await $`${pythonPath} -m venv ${MANAGED_PYTHON_ENV}`.quiet().nothrow();
184
212
  if (createEnv.exitCode !== 0) {
185
213
  return { success: false, usedManagedEnv: true };
186
214
  }
187
- const installInManagedEnv = await $`${uvPath} pip install --python ${MANAGED_PYTHON_ENV} ${packages}`.nothrow();
188
- return { success: installInManagedEnv.exitCode === 0, usedManagedEnv: true };
189
215
  }
190
216
 
191
- const createEnv = await $`${pythonPath} -m venv ${MANAGED_PYTHON_ENV}`.quiet().nothrow();
192
- if (createEnv.exitCode !== 0) {
193
- return { success: false, usedManagedEnv: true };
194
- }
195
-
196
- const managedPython = managedPythonPath();
197
- const installInManagedEnv = await $`${managedPython} -m pip install ${packages}`.nothrow();
198
- return { success: installInManagedEnv.exitCode === 0, usedManagedEnv: true };
217
+ // Ensure pip is available in the managed env
218
+ await $`${managedPython} -m ensurepip`.quiet().nothrow();
219
+ const result = await $`${managedPython} -m pip install ${packages}`.nothrow();
220
+ return { success: result.exitCode === 0, usedManagedEnv: true };
199
221
  }
200
222
 
201
223
  /**
@@ -258,7 +280,13 @@ async function handlePythonSetup(flags: { json?: boolean; check?: boolean }): Pr
258
280
  }
259
281
 
260
282
  console.log("");
261
- const install = await installPythonPackages(check.missingPackages, check.pythonPath, check.uvPath, check.pipPath);
283
+ const install = await installPythonPackages(
284
+ check.missingPackages,
285
+ check.pythonPath,
286
+ check.uvPath,
287
+ check.pipPath,
288
+ check.usingManagedEnv,
289
+ );
262
290
 
263
291
  if (!install.success) {
264
292
  console.error(chalk.red(`\n${theme.status.error} Installation failed`));
package/src/ipy/kernel.ts CHANGED
@@ -129,8 +129,7 @@ export async function checkPythonKernelAvailability(cwd: string): Promise<Python
129
129
  return {
130
130
  ok: false,
131
131
  pythonPath: runtime.pythonPath,
132
- reason:
133
- "kernel_gateway (jupyter-kernel-gateway) or ipykernel not installed. Run: python -m pip install jupyter_kernel_gateway ipykernel",
132
+ reason: "kernel_gateway (jupyter-kernel-gateway) or ipykernel not installed. Run: arcane setup python",
134
133
  };
135
134
  } catch (err: unknown) {
136
135
  return { ok: false, reason: err instanceof Error ? err.message : String(err) };