@paretools/python 0.8.5 → 0.10.0

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 (62) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/lib/formatters.d.ts +52 -5
  5. package/dist/lib/formatters.d.ts.map +1 -1
  6. package/dist/lib/formatters.js +287 -37
  7. package/dist/lib/formatters.js.map +1 -1
  8. package/dist/lib/parsers.d.ts +30 -15
  9. package/dist/lib/parsers.d.ts.map +1 -1
  10. package/dist/lib/parsers.js +506 -51
  11. package/dist/lib/parsers.js.map +1 -1
  12. package/dist/lib/python-runner.d.ts +2 -0
  13. package/dist/lib/python-runner.d.ts.map +1 -1
  14. package/dist/lib/python-runner.js +12 -8
  15. package/dist/lib/python-runner.js.map +1 -1
  16. package/dist/schemas/index.d.ts +354 -69
  17. package/dist/schemas/index.d.ts.map +1 -1
  18. package/dist/schemas/index.js +266 -32
  19. package/dist/schemas/index.js.map +1 -1
  20. package/dist/tools/black.d.ts.map +1 -1
  21. package/dist/tools/black.js +45 -10
  22. package/dist/tools/black.js.map +1 -1
  23. package/dist/tools/conda.d.ts.map +1 -1
  24. package/dist/tools/conda.js +73 -14
  25. package/dist/tools/conda.js.map +1 -1
  26. package/dist/tools/mypy.d.ts.map +1 -1
  27. package/dist/tools/mypy.js +168 -13
  28. package/dist/tools/mypy.js.map +1 -1
  29. package/dist/tools/pip-audit.d.ts.map +1 -1
  30. package/dist/tools/pip-audit.js +75 -15
  31. package/dist/tools/pip-audit.js.map +1 -1
  32. package/dist/tools/pip-install.d.ts.map +1 -1
  33. package/dist/tools/pip-install.js +88 -14
  34. package/dist/tools/pip-install.js.map +1 -1
  35. package/dist/tools/pip-list.d.ts.map +1 -1
  36. package/dist/tools/pip-list.js +58 -13
  37. package/dist/tools/pip-list.js.map +1 -1
  38. package/dist/tools/pip-show.d.ts.map +1 -1
  39. package/dist/tools/pip-show.js +46 -12
  40. package/dist/tools/pip-show.js.map +1 -1
  41. package/dist/tools/poetry.d.ts.map +1 -1
  42. package/dist/tools/poetry.js +75 -14
  43. package/dist/tools/poetry.js.map +1 -1
  44. package/dist/tools/pyenv.d.ts.map +1 -1
  45. package/dist/tools/pyenv.js +84 -19
  46. package/dist/tools/pyenv.js.map +1 -1
  47. package/dist/tools/pytest.d.ts.map +1 -1
  48. package/dist/tools/pytest.js +77 -11
  49. package/dist/tools/pytest.js.map +1 -1
  50. package/dist/tools/ruff-format.d.ts.map +1 -1
  51. package/dist/tools/ruff-format.js +84 -9
  52. package/dist/tools/ruff-format.js.map +1 -1
  53. package/dist/tools/ruff.d.ts.map +1 -1
  54. package/dist/tools/ruff.js +87 -11
  55. package/dist/tools/ruff.js.map +1 -1
  56. package/dist/tools/uv-install.d.ts.map +1 -1
  57. package/dist/tools/uv-install.js +79 -14
  58. package/dist/tools/uv-install.js.map +1 -1
  59. package/dist/tools/uv-run.d.ts.map +1 -1
  60. package/dist/tools/uv-run.js +81 -13
  61. package/dist/tools/uv-run.js.map +1 -1
  62. package/package.json +2 -2
@@ -4,7 +4,8 @@ export function formatPipInstall(data) {
4
4
  return "All requirements already satisfied.";
5
5
  if (!data.success)
6
6
  return "pip install failed.";
7
- const lines = [`Installed ${data.total} packages:`];
7
+ const verb = data.dryRun ? "Would install" : "Installed";
8
+ const lines = [`${verb} ${data.total} packages:`];
8
9
  for (const pkg of data.installed ?? []) {
9
10
  lines.push(` ${pkg.name}==${pkg.version}`);
10
11
  }
@@ -14,7 +15,7 @@ export function formatPipInstall(data) {
14
15
  export function formatMypy(data) {
15
16
  if (data.success && data.total === 0)
16
17
  return "mypy: no errors found.";
17
- const lines = [`mypy: ${data.errors} errors, ${data.warnings} warnings/notes`];
18
+ const lines = [`mypy: ${data.errors} errors, ${data.warnings} warnings, ${data.notes} notes`];
18
19
  for (const d of data.diagnostics ?? []) {
19
20
  const col = d.column ? `:${d.column}` : "";
20
21
  const code = d.code ? ` [${d.code}]` : "";
@@ -26,9 +27,11 @@ export function formatMypy(data) {
26
27
  export function formatRuff(data) {
27
28
  if (data.total === 0)
28
29
  return "ruff: no issues found.";
29
- const lines = [`ruff: ${data.total} issues (${data.fixable} fixable)`];
30
+ const fixedPart = data.fixedCount !== undefined ? `, ${data.fixedCount} fixed` : "";
31
+ const lines = [`ruff: ${data.total} issues (${data.fixable} fixable${fixedPart})`];
30
32
  for (const d of data.diagnostics ?? []) {
31
- lines.push(` ${d.file}:${d.line}:${d.column} ${d.code}: ${d.message}`);
33
+ const fixInfo = d.fixApplicability ? ` [fix: ${d.fixApplicability}]` : "";
34
+ lines.push(` ${d.file}:${d.line}:${d.column} ${d.code}: ${d.message}${fixInfo}`);
32
35
  }
33
36
  return lines.join("\n");
34
37
  }
@@ -39,7 +42,9 @@ export function formatPipAudit(data) {
39
42
  const lines = [`${data.total} vulnerabilities:`];
40
43
  for (const v of data.vulnerabilities ?? []) {
41
44
  const fix = v.fixVersions.length ? ` (fix: ${v.fixVersions.join(", ")})` : "";
42
- lines.push(` ${v.name}==${v.version} ${v.id}: ${v.description}${fix}`);
45
+ const severity = v.severity ? ` [${v.severity}]` : "";
46
+ const score = v.cvssScore != null ? ` CVSS:${v.cvssScore}` : "";
47
+ lines.push(` ${v.name}==${v.version} ${v.id}${severity}${score}: ${v.description}${fix}`);
43
48
  }
44
49
  return lines.join("\n");
45
50
  }
@@ -56,6 +61,8 @@ export function formatPytest(data) {
56
61
  parts.push(`${data.errors} errors`);
57
62
  if (data.skipped > 0)
58
63
  parts.push(`${data.skipped} skipped`);
64
+ if (data.warnings > 0)
65
+ parts.push(`${data.warnings} warnings`);
59
66
  const lines = [`pytest: ${parts.join(", ")} in ${data.duration}s`];
60
67
  for (const f of data.failures ?? []) {
61
68
  lines.push(` FAILED ${f.test}: ${f.message}`);
@@ -64,9 +71,20 @@ export function formatPytest(data) {
64
71
  }
65
72
  /** Formats structured uv install results into a human-readable summary. */
66
73
  export function formatUvInstall(data) {
67
- if (!data.success)
68
- return "uv install failed.";
69
- if (data.total === 0)
74
+ if (!data.success) {
75
+ const lines = ["uv install failed."];
76
+ if (data.resolutionConflicts && data.resolutionConflicts.length > 0) {
77
+ lines.push("Resolution conflicts:");
78
+ for (const c of data.resolutionConflicts) {
79
+ lines.push(` ${c.package} ${c.constraint}`);
80
+ }
81
+ }
82
+ else if (data.error) {
83
+ lines.push(data.error);
84
+ }
85
+ return lines.join("\n");
86
+ }
87
+ if (data.alreadySatisfied || data.total === 0)
70
88
  return "All requirements already satisfied.";
71
89
  const lines = [`Installed ${data.total} packages in ${data.duration}s:`];
72
90
  for (const pkg of data.installed ?? []) {
@@ -78,16 +96,34 @@ export function formatUvInstall(data) {
78
96
  export function formatUvRun(data) {
79
97
  const status = data.success ? "completed" : `failed (exit ${data.exitCode})`;
80
98
  const lines = [`uv run ${status} in ${data.duration}s`];
99
+ if (data.uvDiagnostics && data.uvDiagnostics.length > 0) {
100
+ lines.push("uv diagnostics:");
101
+ for (const d of data.uvDiagnostics) {
102
+ lines.push(` ${d}`);
103
+ }
104
+ }
81
105
  if (data.stdout?.trim()) {
82
106
  lines.push("stdout:", data.stdout.trim());
83
107
  }
84
- if (data.stderr?.trim()) {
85
- lines.push("stderr:", data.stderr.trim());
108
+ const commandErr = data.commandStderr ?? data.stderr;
109
+ if (commandErr?.trim()) {
110
+ lines.push("stderr:", commandErr.trim());
111
+ }
112
+ if (data.truncated) {
113
+ lines.push("output truncated");
86
114
  }
87
115
  return lines.join("\n");
88
116
  }
89
117
  /** Formats structured Black formatter results into a human-readable summary. */
90
118
  export function formatBlack(data) {
119
+ if (data.errorType === "internal_error") {
120
+ if (data.diagnostics && data.diagnostics.length > 0) {
121
+ const first = data.diagnostics[0];
122
+ const col = first.column !== undefined ? `:${first.column}` : "";
123
+ return `black: internal error (exit 123). ${first.file}:${first.line}${col} ${first.message}`;
124
+ }
125
+ return "black: internal error (exit 123). Check for syntax errors.";
126
+ }
91
127
  if (data.filesChecked === 0)
92
128
  return "black: no Python files found.";
93
129
  if (data.success && data.filesChanged === 0) {
@@ -96,7 +132,7 @@ export function formatBlack(data) {
96
132
  const lines = [];
97
133
  const wouldReformat = data.wouldReformat ?? [];
98
134
  if (wouldReformat.length > 0) {
99
- lines.push(`black: ${data.filesChanged} files ${data.success ? "reformatted" : "would be reformatted"}, ${data.filesUnchanged} unchanged`);
135
+ lines.push(`black: ${data.filesChanged} files ${data.errorType === "check_failed" ? "would be reformatted" : "reformatted"}, ${data.filesUnchanged} unchanged`);
100
136
  for (const f of wouldReformat) {
101
137
  lines.push(` ${f}`);
102
138
  }
@@ -113,6 +149,7 @@ export function compactPytestMap(data) {
113
149
  failed: data.failed,
114
150
  errors: data.errors,
115
151
  skipped: data.skipped,
152
+ warnings: data.warnings,
116
153
  total: data.total,
117
154
  duration: data.duration,
118
155
  failedTests: (data.failures ?? []).map((f) => f.test),
@@ -130,6 +167,8 @@ export function formatPytestCompact(data) {
130
167
  parts.push(`${data.errors} errors`);
131
168
  if (data.skipped > 0)
132
169
  parts.push(`${data.skipped} skipped`);
170
+ if (data.warnings > 0)
171
+ parts.push(`${data.warnings} warnings`);
133
172
  const lines = [`pytest: ${parts.join(", ")} in ${data.duration}s`];
134
173
  for (const t of data.failedTests) {
135
174
  lines.push(` FAILED ${t}`);
@@ -142,23 +181,27 @@ export function compactMypyMap(data) {
142
181
  total: data.total,
143
182
  errors: data.errors,
144
183
  warnings: data.warnings,
184
+ notes: data.notes,
145
185
  };
146
186
  }
147
187
  export function formatMypyCompact(data) {
148
188
  if (data.success && data.total === 0)
149
189
  return "mypy: no errors found.";
150
- return `mypy: ${data.errors} errors, ${data.warnings} warnings/notes (${data.total} total)`;
190
+ return `mypy: ${data.errors} errors, ${data.warnings} warnings, ${data.notes} notes (${data.total} total)`;
151
191
  }
152
192
  export function compactRuffMap(data) {
153
193
  return {
194
+ success: data.success,
154
195
  total: data.total,
155
196
  fixable: data.fixable,
197
+ fixedCount: data.fixedCount,
156
198
  };
157
199
  }
158
200
  export function formatRuffCompact(data) {
159
201
  if (data.total === 0)
160
202
  return "ruff: no issues found.";
161
- return `ruff: ${data.total} issues (${data.fixable} fixable)`;
203
+ const fixedPart = data.fixedCount !== undefined ? `, ${data.fixedCount} fixed` : "";
204
+ return `ruff: ${data.total} issues (${data.fixable} fixable${fixedPart})`;
162
205
  }
163
206
  export function compactBlackMap(data) {
164
207
  return {
@@ -166,9 +209,13 @@ export function compactBlackMap(data) {
166
209
  filesChanged: data.filesChanged,
167
210
  filesUnchanged: data.filesUnchanged,
168
211
  filesChecked: data.filesChecked,
212
+ errorType: data.errorType,
169
213
  };
170
214
  }
171
215
  export function formatBlackCompact(data) {
216
+ if (data.errorType === "internal_error") {
217
+ return "black: internal error (exit 123).";
218
+ }
172
219
  if (data.filesChecked === 0)
173
220
  return "black: no Python files found.";
174
221
  if (data.filesChanged === 0)
@@ -180,6 +227,7 @@ export function compactPipInstallMap(data) {
180
227
  success: data.success,
181
228
  total: data.total,
182
229
  alreadySatisfied: data.alreadySatisfied,
230
+ dryRun: data.dryRun || undefined,
183
231
  };
184
232
  }
185
233
  export function formatPipInstallCompact(data) {
@@ -187,10 +235,12 @@ export function formatPipInstallCompact(data) {
187
235
  return "All requirements already satisfied.";
188
236
  if (!data.success)
189
237
  return "pip install failed.";
190
- return `Installed ${data.total} packages.`;
238
+ const verb = data.dryRun ? "Would install" : "Installed";
239
+ return `${verb} ${data.total} packages.`;
191
240
  }
192
241
  export function compactPipAuditMap(data) {
193
242
  return {
243
+ success: data.success,
194
244
  total: data.total,
195
245
  };
196
246
  }
@@ -204,12 +254,19 @@ export function compactUvInstallMap(data) {
204
254
  success: data.success,
205
255
  total: data.total,
206
256
  duration: data.duration,
257
+ alreadySatisfied: data.alreadySatisfied,
258
+ error: data.error,
259
+ resolutionConflicts: data.resolutionConflicts,
207
260
  };
208
261
  }
209
262
  export function formatUvInstallCompact(data) {
210
- if (!data.success)
263
+ if (!data.success) {
264
+ if (data.resolutionConflicts && data.resolutionConflicts.length > 0) {
265
+ return `uv install failed: ${data.resolutionConflicts.length} resolution conflicts.`;
266
+ }
211
267
  return "uv install failed.";
212
- if (data.total === 0)
268
+ }
269
+ if (data.alreadySatisfied || data.total === 0)
213
270
  return "All requirements already satisfied.";
214
271
  return `Installed ${data.total} packages in ${data.duration}s.`;
215
272
  }
@@ -218,15 +275,19 @@ export function compactUvRunMap(data) {
218
275
  exitCode: data.exitCode,
219
276
  success: data.success,
220
277
  duration: data.duration,
278
+ truncated: data.truncated,
221
279
  };
222
280
  }
223
281
  export function formatUvRunCompact(data) {
224
282
  const status = data.success ? "completed" : `failed (exit ${data.exitCode})`;
225
- return `uv run ${status} in ${data.duration}s`;
283
+ const truncated = data.truncated ? " (truncated)" : "";
284
+ return `uv run ${status} in ${data.duration}s${truncated}`;
226
285
  }
227
286
  // ── pip-list formatters ──────────────────────────────────────────────
228
287
  /** Formats structured pip list results into a human-readable package listing. */
229
288
  export function formatPipList(data) {
289
+ if (data.error)
290
+ return `pip list error: ${data.error}`;
230
291
  if (data.total === 0)
231
292
  return "No packages installed.";
232
293
  const lines = [`${data.total} packages installed:`];
@@ -237,10 +298,14 @@ export function formatPipList(data) {
237
298
  }
238
299
  export function compactPipListMap(data) {
239
300
  return {
301
+ success: data.success,
240
302
  total: data.total,
303
+ error: data.error,
241
304
  };
242
305
  }
243
306
  export function formatPipListCompact(data) {
307
+ if (data.error)
308
+ return `pip list error: ${data.error}`;
244
309
  if (data.total === 0)
245
310
  return "No packages installed.";
246
311
  return `${data.total} packages installed.`;
@@ -250,43 +315,72 @@ export function formatPipListCompact(data) {
250
315
  export function formatPipShow(data) {
251
316
  if (!data.name)
252
317
  return "Package not found.";
253
- const lines = [`${data.name}==${data.version}`];
254
- if (data.summary)
255
- lines.push(` Summary: ${data.summary}`);
256
- if (data.author)
257
- lines.push(` Author: ${data.author}`);
258
- if (data.license)
259
- lines.push(` License: ${data.license}`);
260
- if (data.homepage)
261
- lines.push(` Homepage: ${data.homepage}`);
262
- if (data.location)
263
- lines.push(` Location: ${data.location}`);
264
- const requires = data.requires ?? [];
318
+ // If multiple packages, format each
319
+ if (data.packages && data.packages.length > 1) {
320
+ const sections = [];
321
+ for (const pkg of data.packages) {
322
+ sections.push(formatSinglePipShowPackage(pkg));
323
+ }
324
+ return sections.join("\n---\n");
325
+ }
326
+ return formatSinglePipShowPackage(data);
327
+ }
328
+ function formatSinglePipShowPackage(pkg) {
329
+ const lines = [`${pkg.name}==${pkg.version}`];
330
+ if (pkg.summary)
331
+ lines.push(` Summary: ${pkg.summary}`);
332
+ if (pkg.author)
333
+ lines.push(` Author: ${pkg.author}`);
334
+ if (pkg.authorEmail)
335
+ lines.push(` Author-email: ${pkg.authorEmail}`);
336
+ if (pkg.license)
337
+ lines.push(` License: ${pkg.license}`);
338
+ if (pkg.homepage)
339
+ lines.push(` Homepage: ${pkg.homepage}`);
340
+ if (pkg.location)
341
+ lines.push(` Location: ${pkg.location}`);
342
+ if (pkg.metadataVersion)
343
+ lines.push(` Metadata-Version: ${pkg.metadataVersion}`);
344
+ const requires = pkg.requires ?? [];
265
345
  if (requires.length > 0)
266
346
  lines.push(` Requires: ${requires.join(", ")}`);
347
+ const requiredBy = pkg.requiredBy ?? [];
348
+ if (requiredBy.length > 0)
349
+ lines.push(` Required-by: ${requiredBy.join(", ")}`);
350
+ const classifiers = pkg.classifiers ?? [];
351
+ if (classifiers.length > 0)
352
+ lines.push(` Classifiers: ${classifiers.join(", ")}`);
267
353
  return lines.join("\n");
268
354
  }
269
355
  export function compactPipShowMap(data) {
270
356
  return {
357
+ success: data.success,
271
358
  name: data.name,
272
359
  version: data.version,
273
360
  summary: data.summary,
361
+ requires: data.requires ?? [],
362
+ packageCount: data.packages?.length ?? 1,
274
363
  };
275
364
  }
276
365
  export function formatPipShowCompact(data) {
277
366
  if (!data.name)
278
367
  return "Package not found.";
368
+ if (data.packageCount > 1) {
369
+ return `${data.name}==${data.version}: ${data.summary} (+${data.packageCount - 1} more)`;
370
+ }
279
371
  return `${data.name}==${data.version}: ${data.summary}`;
280
372
  }
281
373
  // ── ruff-format formatters ───────────────────────────────────────────
282
374
  /** Formats structured ruff format results into a human-readable summary. */
283
375
  export function formatRuffFormat(data) {
284
376
  if (data.success && data.filesChanged === 0) {
285
- return "ruff format: all files already formatted.";
377
+ const unchanged = data.filesUnchanged > 0 ? ` (${data.filesUnchanged} unchanged)` : "";
378
+ return `ruff format: all files already formatted.${unchanged}`;
286
379
  }
287
380
  const lines = [];
288
- const verb = data.success ? "reformatted" : "would be reformatted";
289
- lines.push(`ruff format: ${data.filesChanged} files ${verb}`);
381
+ const verb = data.checkMode ? "would be reformatted" : "reformatted";
382
+ const unchanged = data.filesUnchanged > 0 ? `, ${data.filesUnchanged} unchanged` : "";
383
+ lines.push(`ruff format: ${data.filesChanged} files ${verb}${unchanged}`);
290
384
  if (data.files && data.files.length > 0) {
291
385
  for (const f of data.files) {
292
386
  lines.push(` ${f}`);
@@ -298,18 +392,24 @@ export function compactRuffFormatMap(data) {
298
392
  return {
299
393
  success: data.success,
300
394
  filesChanged: data.filesChanged,
395
+ filesUnchanged: data.filesUnchanged,
396
+ checkMode: data.checkMode || undefined,
301
397
  };
302
398
  }
303
399
  export function formatRuffFormatCompact(data) {
304
400
  if (data.success && data.filesChanged === 0) {
305
- return "ruff format: all files already formatted.";
401
+ const unchanged = data.filesUnchanged > 0 ? ` (${data.filesUnchanged} unchanged)` : "";
402
+ return `ruff format: all files already formatted.${unchanged}`;
306
403
  }
307
- const verb = data.success ? "reformatted" : "would be reformatted";
308
- return `ruff format: ${data.filesChanged} files ${verb}`;
404
+ const verb = data.checkMode ? "would be reformatted" : "reformatted";
405
+ const unchanged = data.filesUnchanged > 0 ? `, ${data.filesUnchanged} unchanged` : "";
406
+ return `ruff format: ${data.filesChanged} files ${verb}${unchanged}`;
309
407
  }
310
408
  // ── conda formatters ─────────────────────────────────────────────────
311
409
  /** Formats structured conda list results into a human-readable package listing. */
312
410
  export function formatCondaList(data) {
411
+ if (data.parseError)
412
+ return `conda list parse error: ${data.parseError}`;
313
413
  if (data.total === 0)
314
414
  return "conda: no packages found.";
315
415
  const env = data.environment ? ` (env: ${data.environment})` : "";
@@ -321,6 +421,8 @@ export function formatCondaList(data) {
321
421
  }
322
422
  /** Formats structured conda info results into a human-readable summary. */
323
423
  export function formatCondaInfo(data) {
424
+ if (data.parseError)
425
+ return `conda info parse error: ${data.parseError}`;
324
426
  const lines = [
325
427
  `conda ${data.condaVersion}`,
326
428
  ` platform: ${data.platform}`,
@@ -337,6 +439,8 @@ export function formatCondaInfo(data) {
337
439
  }
338
440
  /** Formats structured conda env list results into a human-readable listing. */
339
441
  export function formatCondaEnvList(data) {
442
+ if (data.parseError)
443
+ return `conda env list parse error: ${data.parseError}`;
340
444
  if (data.total === 0)
341
445
  return "conda: no environments found.";
342
446
  const lines = [`conda environments: ${data.total}`];
@@ -346,6 +450,36 @@ export function formatCondaEnvList(data) {
346
450
  }
347
451
  return lines.join("\n");
348
452
  }
453
+ function formatCondaCreate(data) {
454
+ if (!data.success)
455
+ return `conda create failed: ${data.error || "unknown error"}`;
456
+ const target = data.environment
457
+ ? ` (${data.environment})`
458
+ : data.prefix
459
+ ? ` (${data.prefix})`
460
+ : "";
461
+ return `conda create${target}: ${data.totalAdded} packages added.`;
462
+ }
463
+ function formatCondaRemove(data) {
464
+ if (!data.success)
465
+ return `conda remove failed: ${data.error || "unknown error"}`;
466
+ const target = data.environment
467
+ ? ` (${data.environment})`
468
+ : data.prefix
469
+ ? ` (${data.prefix})`
470
+ : "";
471
+ return `conda remove${target}: ${data.totalRemoved} packages removed.`;
472
+ }
473
+ function formatCondaUpdate(data) {
474
+ if (!data.success)
475
+ return `conda update failed: ${data.error || "unknown error"}`;
476
+ const target = data.environment
477
+ ? ` (${data.environment})`
478
+ : data.prefix
479
+ ? ` (${data.prefix})`
480
+ : "";
481
+ return `conda update${target}: ${data.totalUpdated} packages changed.`;
482
+ }
349
483
  /** Formats any CondaResult variant into human-readable text. */
350
484
  export function formatCondaResult(data) {
351
485
  switch (data.action) {
@@ -355,6 +489,12 @@ export function formatCondaResult(data) {
355
489
  return formatCondaInfo(data);
356
490
  case "env-list":
357
491
  return formatCondaEnvList(data);
492
+ case "create":
493
+ return formatCondaCreate(data);
494
+ case "remove":
495
+ return formatCondaRemove(data);
496
+ case "update":
497
+ return formatCondaUpdate(data);
358
498
  default:
359
499
  return "conda: unknown action.";
360
500
  }
@@ -364,9 +504,12 @@ export function compactCondaListMap(data) {
364
504
  action: "list",
365
505
  total: data.total,
366
506
  environment: data.environment,
507
+ parseError: data.parseError,
367
508
  };
368
509
  }
369
510
  export function formatCondaListCompact(data) {
511
+ if (data.parseError)
512
+ return `conda list parse error: ${data.parseError}`;
370
513
  if (data.total === 0)
371
514
  return "conda: no packages found.";
372
515
  const env = data.environment ? ` (env: ${data.environment})` : "";
@@ -378,22 +521,67 @@ export function compactCondaInfoMap(data) {
378
521
  condaVersion: data.condaVersion,
379
522
  platform: data.platform,
380
523
  pythonVersion: data.pythonVersion,
524
+ parseError: data.parseError,
381
525
  };
382
526
  }
383
527
  export function formatCondaInfoCompact(data) {
528
+ if (data.parseError)
529
+ return `conda info parse error: ${data.parseError}`;
384
530
  return `conda ${data.condaVersion} (${data.platform}, python ${data.pythonVersion})`;
385
531
  }
386
532
  export function compactCondaEnvListMap(data) {
387
533
  return {
388
534
  action: "env-list",
389
535
  total: data.total,
536
+ parseError: data.parseError,
390
537
  };
391
538
  }
392
539
  export function formatCondaEnvListCompact(data) {
540
+ if (data.parseError)
541
+ return `conda env list parse error: ${data.parseError}`;
393
542
  if (data.total === 0)
394
543
  return "conda: no environments found.";
395
544
  return `conda: ${data.total} environments.`;
396
545
  }
546
+ function compactCondaCreateMap(data) {
547
+ return {
548
+ action: "create",
549
+ success: data.success,
550
+ totalAdded: data.totalAdded,
551
+ error: data.error,
552
+ };
553
+ }
554
+ function compactCondaRemoveMap(data) {
555
+ return {
556
+ action: "remove",
557
+ success: data.success,
558
+ totalRemoved: data.totalRemoved,
559
+ error: data.error,
560
+ };
561
+ }
562
+ function compactCondaUpdateMap(data) {
563
+ return {
564
+ action: "update",
565
+ success: data.success,
566
+ totalUpdated: data.totalUpdated,
567
+ error: data.error,
568
+ };
569
+ }
570
+ function formatCondaCreateCompact(data) {
571
+ if (!data.success)
572
+ return "conda create failed.";
573
+ return `conda create: ${data.totalAdded} packages added.`;
574
+ }
575
+ function formatCondaRemoveCompact(data) {
576
+ if (!data.success)
577
+ return "conda remove failed.";
578
+ return `conda remove: ${data.totalRemoved} packages removed.`;
579
+ }
580
+ function formatCondaUpdateCompact(data) {
581
+ if (!data.success)
582
+ return "conda update failed.";
583
+ return `conda update: ${data.totalUpdated} packages changed.`;
584
+ }
397
585
  export function compactCondaResultMap(data) {
398
586
  switch (data.action) {
399
587
  case "list":
@@ -402,6 +590,12 @@ export function compactCondaResultMap(data) {
402
590
  return compactCondaInfoMap(data);
403
591
  case "env-list":
404
592
  return compactCondaEnvListMap(data);
593
+ case "create":
594
+ return compactCondaCreateMap(data);
595
+ case "remove":
596
+ return compactCondaRemoveMap(data);
597
+ case "update":
598
+ return compactCondaUpdateMap(data);
405
599
  default:
406
600
  return { action: "list", total: 0 };
407
601
  }
@@ -414,6 +608,12 @@ export function formatCondaResultCompact(data) {
414
608
  return formatCondaInfoCompact(data);
415
609
  case "env-list":
416
610
  return formatCondaEnvListCompact(data);
611
+ case "create":
612
+ return formatCondaCreateCompact(data);
613
+ case "remove":
614
+ return formatCondaRemoveCompact(data);
615
+ case "update":
616
+ return formatCondaUpdateCompact(data);
417
617
  }
418
618
  }
419
619
  // ── pyenv formatters ─────────────────────────────────────────────────
@@ -434,10 +634,24 @@ export function formatPyenv(data) {
434
634
  }
435
635
  case "version":
436
636
  return data.current ? `pyenv: current version is ${data.current}` : "pyenv: no version set.";
637
+ case "installList": {
638
+ const avail = data.availableVersions ?? [];
639
+ if (avail.length === 0)
640
+ return "pyenv: no versions available.";
641
+ const lines = [`${avail.length} versions available for installation:`];
642
+ for (const v of avail) {
643
+ lines.push(` ${v}`);
644
+ }
645
+ return lines.join("\n");
646
+ }
437
647
  case "install":
438
648
  return data.installed
439
649
  ? `pyenv: installed Python ${data.installed}`
440
650
  : "pyenv: installation completed.";
651
+ case "uninstall":
652
+ return data.uninstalled
653
+ ? `pyenv: uninstalled Python ${data.uninstalled}`
654
+ : "pyenv: uninstall completed.";
441
655
  case "local":
442
656
  return data.localVersion
443
657
  ? `pyenv: local version set to ${data.localVersion}`
@@ -446,17 +660,39 @@ export function formatPyenv(data) {
446
660
  return data.globalVersion
447
661
  ? `pyenv: global version set to ${data.globalVersion}`
448
662
  : "pyenv: global version set.";
663
+ case "which":
664
+ return data.commandPath
665
+ ? `pyenv: resolved command path ${data.commandPath}`
666
+ : "pyenv: command path not found.";
667
+ case "rehash":
668
+ return "pyenv: shims rehashed.";
449
669
  }
450
670
  }
451
671
  export function compactPyenvMap(data) {
672
+ let keyValue;
673
+ if (data.action === "version")
674
+ keyValue = data.current;
675
+ if (data.action === "local")
676
+ keyValue = data.localVersion;
677
+ if (data.action === "global")
678
+ keyValue = data.globalVersion;
679
+ if (data.action === "install")
680
+ keyValue = data.installed;
681
+ if (data.action === "uninstall")
682
+ keyValue = data.uninstalled;
683
+ if (data.action === "which")
684
+ keyValue = data.commandPath;
452
685
  return {
453
686
  action: data.action,
454
687
  success: data.success,
688
+ keyValue,
455
689
  };
456
690
  }
457
691
  export function formatPyenvCompact(data) {
458
692
  if (!data.success)
459
693
  return `pyenv ${data.action} failed.`;
694
+ if (data.keyValue)
695
+ return `pyenv ${data.action}: ${data.keyValue}`;
460
696
  return `pyenv ${data.action}: success.`;
461
697
  }
462
698
  // ── poetry formatters ────────────────────────────────────────────────
@@ -470,7 +706,8 @@ export function formatPoetry(data) {
470
706
  return "No packages found.";
471
707
  const lines = [`${pkgs.length} packages:`];
472
708
  for (const pkg of pkgs) {
473
- lines.push(` ${pkg.name}==${pkg.version}`);
709
+ const desc = pkg.description ? ` - ${pkg.description}` : "";
710
+ lines.push(` ${pkg.name}==${pkg.version}${desc}`);
474
711
  }
475
712
  return lines.join("\n");
476
713
  }
@@ -484,7 +721,17 @@ export function formatPoetry(data) {
484
721
  }
485
722
  return lines.join("\n");
486
723
  }
487
- // install, add, remove
724
+ if (data.action === "check" || data.action === "lock" || data.action === "export") {
725
+ const msgs = data.messages ?? [];
726
+ if (msgs.length === 0)
727
+ return `poetry ${data.action}: success.`;
728
+ const lines = [`poetry ${data.action}:`];
729
+ for (const m of msgs) {
730
+ lines.push(` ${m}`);
731
+ }
732
+ return lines.join("\n");
733
+ }
734
+ // install, add, remove, update
488
735
  const pkgs = data.packages ?? [];
489
736
  if (pkgs.length === 0)
490
737
  return `poetry ${data.action}: no changes.`;
@@ -514,6 +761,9 @@ export function formatPoetryCompact(data) {
514
761
  return "poetry build: no artifacts produced.";
515
762
  return `Built ${data.total} artifacts.`;
516
763
  }
764
+ if (data.action === "check" || data.action === "lock" || data.action === "export") {
765
+ return `poetry ${data.action}: success.`;
766
+ }
517
767
  if (data.total === 0)
518
768
  return `poetry ${data.action}: no changes.`;
519
769
  return `poetry ${data.action}: ${data.total} packages.`;