@wrongstack/tools 0.293.0 → 0.295.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 (248) hide show
  1. package/dist/_env.d.ts +1 -1
  2. package/dist/_env.d.ts.map +1 -1
  3. package/dist/_fetch-guard.d.ts.map +1 -1
  4. package/dist/_spawn-stream.d.ts +1 -1
  5. package/dist/_spawn-stream.d.ts.map +1 -1
  6. package/dist/_util.d.ts +1 -1
  7. package/dist/_util.d.ts.map +1 -1
  8. package/dist/audit.d.ts +1 -1
  9. package/dist/audit.d.ts.map +1 -1
  10. package/dist/audit.js +81 -16
  11. package/dist/audit.js.map +2 -2
  12. package/dist/bash.d.ts +1 -1
  13. package/dist/bash.d.ts.map +1 -1
  14. package/dist/bash.js +66 -52
  15. package/dist/bash.js.map +3 -3
  16. package/dist/batch-tool-use.d.ts +1 -1
  17. package/dist/batch-tool-use.d.ts.map +1 -1
  18. package/dist/batch-tool-use.js +1 -1
  19. package/dist/batch-tool-use.js.map +1 -1
  20. package/dist/browser/index.js +10 -1
  21. package/dist/browser/index.js.map +2 -2
  22. package/dist/browser/manager.d.ts +2 -0
  23. package/dist/browser/manager.d.ts.map +1 -1
  24. package/dist/browser/tools.d.ts +1 -1
  25. package/dist/browser/tools.d.ts.map +1 -1
  26. package/dist/builtin.d.ts +1 -1
  27. package/dist/builtin.d.ts.map +1 -1
  28. package/dist/builtin.js +1394 -553
  29. package/dist/builtin.js.map +4 -4
  30. package/dist/codebase-index/background-indexer.d.ts +2 -2
  31. package/dist/codebase-index/background-indexer.d.ts.map +1 -1
  32. package/dist/codebase-index/bm25.d.ts +3 -1
  33. package/dist/codebase-index/bm25.d.ts.map +1 -1
  34. package/dist/codebase-index/codebase-index-tool.d.ts +1 -1
  35. package/dist/codebase-index/codebase-index-tool.d.ts.map +1 -1
  36. package/dist/codebase-index/codebase-search-tool.d.ts +1 -1
  37. package/dist/codebase-index/codebase-search-tool.d.ts.map +1 -1
  38. package/dist/codebase-index/codebase-stats-tool.d.ts +1 -1
  39. package/dist/codebase-index/codebase-stats-tool.d.ts.map +1 -1
  40. package/dist/codebase-index/generic-parser.d.ts +34 -0
  41. package/dist/codebase-index/generic-parser.d.ts.map +1 -0
  42. package/dist/codebase-index/go-parser.d.ts +1 -1
  43. package/dist/codebase-index/go-parser.d.ts.map +1 -1
  44. package/dist/codebase-index/index.d.ts +4 -2
  45. package/dist/codebase-index/index.d.ts.map +1 -1
  46. package/dist/codebase-index/index.js +1036 -341
  47. package/dist/codebase-index/index.js.map +4 -4
  48. package/dist/codebase-index/indexer.d.ts +6 -1
  49. package/dist/codebase-index/indexer.d.ts.map +1 -1
  50. package/dist/codebase-index/json-parser.d.ts +1 -1
  51. package/dist/codebase-index/languages.d.ts +25 -0
  52. package/dist/codebase-index/languages.d.ts.map +1 -0
  53. package/dist/codebase-index/py-parser.d.ts +9 -1
  54. package/dist/codebase-index/py-parser.d.ts.map +1 -1
  55. package/dist/codebase-index/refs-extractor.d.ts.map +1 -1
  56. package/dist/codebase-index/rs-parser.d.ts +1 -1
  57. package/dist/codebase-index/rs-parser.d.ts.map +1 -1
  58. package/dist/codebase-index/schema.d.ts +9 -2
  59. package/dist/codebase-index/schema.d.ts.map +1 -1
  60. package/dist/codebase-index/spawn-gate.d.ts +15 -0
  61. package/dist/codebase-index/spawn-gate.d.ts.map +1 -0
  62. package/dist/codebase-index/ts-parser.d.ts +2 -2
  63. package/dist/codebase-index/ts-parser.d.ts.map +1 -1
  64. package/dist/codebase-index/worker.js +961 -317
  65. package/dist/codebase-index/worker.js.map +4 -4
  66. package/dist/codebase-index/writer.d.ts +83 -4
  67. package/dist/codebase-index/writer.d.ts.map +1 -1
  68. package/dist/codebase-index/yaml-parser.d.ts +1 -1
  69. package/dist/design.d.ts +5 -2
  70. package/dist/design.d.ts.map +1 -1
  71. package/dist/design.js +36 -3
  72. package/dist/design.js.map +2 -2
  73. package/dist/diff.d.ts +1 -1
  74. package/dist/diff.d.ts.map +1 -1
  75. package/dist/diff.js +2 -2
  76. package/dist/diff.js.map +1 -1
  77. package/dist/document.d.ts +1 -1
  78. package/dist/document.d.ts.map +1 -1
  79. package/dist/document.js +1 -1
  80. package/dist/document.js.map +1 -1
  81. package/dist/e2e.d.ts +1 -1
  82. package/dist/e2e.d.ts.map +1 -1
  83. package/dist/e2e.js +1 -1
  84. package/dist/e2e.js.map +1 -1
  85. package/dist/edit.d.ts +1 -1
  86. package/dist/edit.d.ts.map +1 -1
  87. package/dist/edit.js +3 -3
  88. package/dist/edit.js.map +2 -2
  89. package/dist/exec.d.ts +1 -1
  90. package/dist/exec.d.ts.map +1 -1
  91. package/dist/exec.js +60 -21
  92. package/dist/exec.js.map +3 -3
  93. package/dist/fetch.d.ts +1 -1
  94. package/dist/fetch.d.ts.map +1 -1
  95. package/dist/fetch.js +4 -5
  96. package/dist/fetch.js.map +2 -2
  97. package/dist/format.d.ts +1 -1
  98. package/dist/format.d.ts.map +1 -1
  99. package/dist/format.js +81 -16
  100. package/dist/format.js.map +2 -2
  101. package/dist/git.d.ts +1 -1
  102. package/dist/git.d.ts.map +1 -1
  103. package/dist/git.js +3 -2
  104. package/dist/git.js.map +2 -2
  105. package/dist/glob.d.ts +1 -1
  106. package/dist/glob.d.ts.map +1 -1
  107. package/dist/glob.js +2 -2
  108. package/dist/glob.js.map +1 -1
  109. package/dist/grep.d.ts +1 -1
  110. package/dist/grep.d.ts.map +1 -1
  111. package/dist/grep.js +4 -3
  112. package/dist/grep.js.map +2 -2
  113. package/dist/index.d.ts +4 -4
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +1657 -705
  116. package/dist/index.js.map +4 -4
  117. package/dist/install.d.ts +1 -1
  118. package/dist/install.d.ts.map +1 -1
  119. package/dist/install.js +85 -17
  120. package/dist/install.js.map +2 -2
  121. package/dist/json.d.ts +1 -1
  122. package/dist/json.d.ts.map +1 -1
  123. package/dist/json.js +2 -2
  124. package/dist/json.js.map +2 -2
  125. package/dist/kanban.d.ts +4 -3
  126. package/dist/kanban.d.ts.map +1 -1
  127. package/dist/kanban.js +94 -27
  128. package/dist/kanban.js.map +2 -2
  129. package/dist/languages/execute-tool.d.ts +1 -1
  130. package/dist/languages/execute-tool.d.ts.map +1 -1
  131. package/dist/languages/execute.d.ts +1 -1
  132. package/dist/languages/execute.d.ts.map +1 -1
  133. package/dist/languages/index.d.ts +1 -1
  134. package/dist/languages/index.d.ts.map +1 -1
  135. package/dist/languages/index.js +99 -17
  136. package/dist/languages/index.js.map +2 -2
  137. package/dist/languages/package-tool.d.ts +3 -4
  138. package/dist/languages/package-tool.d.ts.map +1 -1
  139. package/dist/languages/plan.d.ts.map +1 -1
  140. package/dist/languages/profiles/additional.d.ts.map +1 -1
  141. package/dist/languages/profiles/primary.d.ts.map +1 -1
  142. package/dist/languages/tool.d.ts +1 -1
  143. package/dist/languages/tool.d.ts.map +1 -1
  144. package/dist/lint.d.ts +1 -1
  145. package/dist/lint.d.ts.map +1 -1
  146. package/dist/lint.js +81 -16
  147. package/dist/lint.js.map +2 -2
  148. package/dist/logs.d.ts +1 -1
  149. package/dist/logs.d.ts.map +1 -1
  150. package/dist/logs.js +2 -2
  151. package/dist/logs.js.map +1 -1
  152. package/dist/memory.d.ts +1 -1
  153. package/dist/memory.d.ts.map +1 -1
  154. package/dist/memory.js +1 -1
  155. package/dist/memory.js.map +1 -1
  156. package/dist/mode.d.ts +1 -1
  157. package/dist/mode.d.ts.map +1 -1
  158. package/dist/mode.js.map +1 -1
  159. package/dist/outdated.d.ts +1 -1
  160. package/dist/outdated.d.ts.map +1 -1
  161. package/dist/outdated.js +101 -19
  162. package/dist/outdated.js.map +2 -2
  163. package/dist/pack.d.ts +1 -1
  164. package/dist/pack.js +1394 -553
  165. package/dist/pack.js.map +4 -4
  166. package/dist/patch.d.ts +1 -1
  167. package/dist/patch.d.ts.map +1 -1
  168. package/dist/patch.js +2 -2
  169. package/dist/patch.js.map +1 -1
  170. package/dist/plan.d.ts +1 -1
  171. package/dist/plan.d.ts.map +1 -1
  172. package/dist/plan.js +7 -7
  173. package/dist/plan.js.map +2 -2
  174. package/dist/process-guardian.d.ts +7 -0
  175. package/dist/process-guardian.d.ts.map +1 -1
  176. package/dist/process-registry-persistent.d.ts +5 -0
  177. package/dist/process-registry-persistent.d.ts.map +1 -1
  178. package/dist/process-registry.d.ts +9 -1
  179. package/dist/process-registry.d.ts.map +1 -1
  180. package/dist/process-registry.js +18 -3
  181. package/dist/process-registry.js.map +2 -2
  182. package/dist/ps-slash.js +54 -15
  183. package/dist/ps-slash.js.map +2 -2
  184. package/dist/read.d.ts +1 -1
  185. package/dist/read.d.ts.map +1 -1
  186. package/dist/read.js +3 -2
  187. package/dist/read.js.map +2 -2
  188. package/dist/replace.d.ts +1 -1
  189. package/dist/replace.d.ts.map +1 -1
  190. package/dist/replace.js +4 -4
  191. package/dist/replace.js.map +2 -2
  192. package/dist/scaffold.d.ts +1 -1
  193. package/dist/scaffold.d.ts.map +1 -1
  194. package/dist/scaffold.js +2 -2
  195. package/dist/scaffold.js.map +1 -1
  196. package/dist/search.d.ts +1 -1
  197. package/dist/search.d.ts.map +1 -1
  198. package/dist/search.js +4 -4
  199. package/dist/search.js.map +2 -2
  200. package/dist/session-kanban.d.ts +4 -1
  201. package/dist/session-kanban.d.ts.map +1 -1
  202. package/dist/session-kanban.js +23 -15
  203. package/dist/session-kanban.js.map +2 -2
  204. package/dist/set-working-dir.d.ts +1 -1
  205. package/dist/set-working-dir.d.ts.map +1 -1
  206. package/dist/skill.d.ts +1 -1
  207. package/dist/skill.d.ts.map +1 -1
  208. package/dist/skill.js +2 -5
  209. package/dist/skill.js.map +2 -2
  210. package/dist/spawn-background.d.ts.map +1 -1
  211. package/dist/task.d.ts +3 -2
  212. package/dist/task.d.ts.map +1 -1
  213. package/dist/task.js +6 -8
  214. package/dist/task.js.map +2 -2
  215. package/dist/test.d.ts +1 -1
  216. package/dist/test.d.ts.map +1 -1
  217. package/dist/test.js +81 -16
  218. package/dist/test.js.map +2 -2
  219. package/dist/todo.d.ts +2 -1
  220. package/dist/todo.d.ts.map +1 -1
  221. package/dist/todo.js +4 -4
  222. package/dist/todo.js.map +2 -2
  223. package/dist/tool-help.d.ts +1 -1
  224. package/dist/tool-help.d.ts.map +1 -1
  225. package/dist/tool-help.js.map +1 -1
  226. package/dist/tool-search.d.ts +1 -1
  227. package/dist/tool-search.d.ts.map +1 -1
  228. package/dist/tool-search.js.map +1 -1
  229. package/dist/tool-tier.d.ts +16 -0
  230. package/dist/tool-tier.d.ts.map +1 -0
  231. package/dist/tool-tier.js +22233 -0
  232. package/dist/tool-tier.js.map +7 -0
  233. package/dist/tool-use.d.ts +1 -1
  234. package/dist/tool-use.d.ts.map +1 -1
  235. package/dist/tool-use.js.map +1 -1
  236. package/dist/tree.d.ts +1 -1
  237. package/dist/tree.d.ts.map +1 -1
  238. package/dist/tree.js +2 -2
  239. package/dist/tree.js.map +1 -1
  240. package/dist/typecheck.d.ts +1 -1
  241. package/dist/typecheck.d.ts.map +1 -1
  242. package/dist/typecheck.js +81 -16
  243. package/dist/typecheck.js.map +2 -2
  244. package/dist/write.d.ts +1 -1
  245. package/dist/write.d.ts.map +1 -1
  246. package/dist/write.js +3 -2
  247. package/dist/write.js.map +2 -2
  248. package/package.json +7 -3
package/dist/install.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Tool } from '@wrongstack/core';
1
+ import type { Tool } from '@wrongstack/core/types';
2
2
  interface InstallInput {
3
3
  packages?: string | string[] | undefined;
4
4
  save?: 'dependency' | 'dev' | 'optional' | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAmB,MAAM,kBAAkB,CAAC;AAM9D,UAAU,YAAY;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IACzC,IAAI,CAAC,EAAE,YAAY,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,CAAC;IACrD,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACxC;AAED,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,WAAW,EAAE,IAAI,CAAC,YAAY,EAAE,aAAa,CA6NzD,CAAC"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAmB,MAAM,wBAAwB,CAAC;AASpE,UAAU,YAAY;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IACzC,IAAI,CAAC,EAAE,YAAY,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,CAAC;IACrD,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACxC;AAED,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,eAAO,MAAM,WAAW,EAAE,IAAI,CAAC,YAAY,EAAE,aAAa,CA6NzD,CAAC"}
package/dist/install.js CHANGED
@@ -1,21 +1,24 @@
1
1
  // src/install.ts
2
2
  import { join as join7 } from "node:path";
3
- import { detectPackageEcosystem, recordPackageAction } from "@wrongstack/core";
3
+ import {
4
+ detectEcosystem as detectPackageEcosystem,
5
+ recordPackageAction
6
+ } from "@wrongstack/core/coordination";
4
7
 
5
8
  // src/_spawn-stream.ts
6
9
  import { spawn as spawn2 } from "node:child_process";
7
10
  import {
8
- buildChildEnv,
9
11
  emitProcessCompleted,
10
12
  emitProcessOutput,
11
13
  emitProcessStarted
12
- } from "@wrongstack/core";
14
+ } from "@wrongstack/core/observability";
15
+ import { buildChildEnv } from "@wrongstack/core/utils";
13
16
 
14
17
  // src/_output-spool.ts
15
18
  import { createWriteStream, mkdirSync } from "node:fs";
16
19
  import * as fsp from "node:fs/promises";
17
20
  import * as path from "node:path";
18
- import { wstackGlobalRoot } from "@wrongstack/core";
21
+ import { wstackGlobalRoot } from "@wrongstack/core/utils";
19
22
  var SPOOL_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
20
23
  var SPOOL_WRITE_HWM_BYTES = 4 * 1024 * 1024;
21
24
  var sweepStarted = false;
@@ -315,7 +318,7 @@ var CircuitBreaker = class {
315
318
  };
316
319
 
317
320
  // src/_redact-command.ts
318
- import { expectDefined } from "@wrongstack/core";
321
+ import { expectDefined } from "@wrongstack/core/utils";
319
322
  var SENSITIVE_FLAG_PATTERNS = [
320
323
  // --flag=value or --flag "value" (value captured up to next space or comma)
321
324
  /--(?:token|password|passwd|pwd|secret|api[-_]?key|api[-_]?secret|auth|credential|private[-_]?key|access[-_]?key|github[-_]?token|gh[-_]?token|bearer|jwt|oauth|pin|pincode|passphrase|access[-_]?token)(?:[=\s,][^\s]*)?/gi,
@@ -409,7 +412,12 @@ var ProcessRegistryImpl = class {
409
412
  this.breaker.setEnabled(false);
410
413
  }
411
414
  register(info) {
412
- this.processes.set(info.pid, { ...info, killed: false, protected: info.protected ?? false });
415
+ this.processes.set(info.pid, {
416
+ ...info,
417
+ killed: false,
418
+ protected: info.protected ?? false,
419
+ background: info.background ?? false
420
+ });
413
421
  }
414
422
  _isSafeSignalPid(pid) {
415
423
  return Number.isInteger(pid) && pid > 1 && pid !== process.pid && pid !== process.ppid;
@@ -462,12 +470,21 @@ var ProcessRegistryImpl = class {
462
470
  }
463
471
  return n;
464
472
  }
473
+ /** Count of active jobs explicitly launched in background mode. */
474
+ get activeBackgroundCount() {
475
+ let n = 0;
476
+ for (const p of this.processes.values()) {
477
+ if (p.background && !p.killed) n++;
478
+ }
479
+ return n;
480
+ }
465
481
  /**
466
482
  * Combined stats for observability — used by /ps and the TUI status bar.
467
483
  */
468
484
  stats() {
469
485
  return {
470
486
  activeCount: this.activeCount,
487
+ backgroundCount: this.activeBackgroundCount,
471
488
  totalCount: this.processes.size,
472
489
  breaker: this.breaker.snapshot()
473
490
  };
@@ -568,7 +585,7 @@ var ProcessRegistryImpl = class {
568
585
  this.autoKillTimer = setTimeout(() => {
569
586
  this.autoKillTimer = null;
570
587
  this.autoKillArmedAt = null;
571
- this.killAll({ force: false });
588
+ this.killAll({ force: false, preserveBackground: true });
572
589
  this.breaker.forceReset();
573
590
  this._emitBreakerCountdown();
574
591
  }, this.autoKillResetMs);
@@ -608,6 +625,7 @@ var ProcessRegistryImpl = class {
608
625
  if (!p) return false;
609
626
  if (p.killed) return true;
610
627
  if (p.protected) return false;
628
+ if (opts.preserveBackground && p.background) return false;
611
629
  const { force = false, graceMs = DEFAULT_GRACE_MS } = opts;
612
630
  const isWin2 = os.platform() === "win32";
613
631
  if (isWin2) {
@@ -959,7 +977,7 @@ async function* spawnStream(opts) {
959
977
 
960
978
  // src/_util.ts
961
979
  import * as path3 from "node:path";
962
- import * as Core from "@wrongstack/core";
980
+ import * as Core from "@wrongstack/core/utils";
963
981
  async function detectPackageManager(cwd) {
964
982
  const { stat: stat5 } = await import("node:fs/promises");
965
983
  try {
@@ -1159,7 +1177,20 @@ function pythonProfile() {
1159
1177
  ]),
1160
1178
  ignoredDirectories: IGNORES,
1161
1179
  packageManagers: Object.freeze(["pip", "poetry", "pipenv", "uv"]),
1162
- executables: Object.freeze(["python", "python3", "ruff", "black", "pytest", "mypy", "pyright"]),
1180
+ executables: Object.freeze([
1181
+ "python",
1182
+ "python3",
1183
+ "pip",
1184
+ "pip3",
1185
+ "poetry",
1186
+ "pipenv",
1187
+ "uv",
1188
+ "ruff",
1189
+ "black",
1190
+ "pytest",
1191
+ "mypy",
1192
+ "pyright"
1193
+ ]),
1163
1194
  operations: Object.freeze({
1164
1195
  syntax: async (ctx) => {
1165
1196
  const py = ctx.options.target ? "python3" : "python3";
@@ -1219,6 +1250,14 @@ function pythonProfile() {
1219
1250
  network: true
1220
1251
  });
1221
1252
  },
1253
+ "package-remove": async (ctx) => {
1254
+ const names = packageNames(ctx);
1255
+ return names.length === 0 ? unavailable(ctx, "package-remove", "At least one package name is required.") : processPlan(ctx, "package-remove", "pip", ["uninstall", "--yes", ...names], {
1256
+ parser: "package-text",
1257
+ reason: "Remove validated Python packages.",
1258
+ mutating: true
1259
+ });
1260
+ },
1222
1261
  "package-audit": async (ctx) => processPlan(ctx, "package-audit", "pip", ["audit"], {
1223
1262
  parser: "pip-audit",
1224
1263
  reason: "Audit Python dependencies for vulnerabilities.",
@@ -1826,6 +1865,19 @@ function typescriptProfile() {
1826
1865
  network: true
1827
1866
  });
1828
1867
  },
1868
+ "package-remove": async (ctx) => {
1869
+ const names = packageNames(ctx);
1870
+ if (names.length === 0)
1871
+ return unavailable(ctx, "package-remove", "At least one package name is required.");
1872
+ const manager = ctx.workspace.packageManager ?? "npm";
1873
+ const args = manager === "npm" ? ["uninstall", "--ignore-scripts", ...names] : ["remove", "--ignore-scripts", ...names];
1874
+ return processPlan(ctx, "package-remove", manager, args, {
1875
+ parser: "package-text",
1876
+ reason: `Remove validated packages with ${manager} and lifecycle scripts disabled.`,
1877
+ mutating: true,
1878
+ network: true
1879
+ });
1880
+ },
1829
1881
  "package-audit": async (ctx) => {
1830
1882
  const manager = ctx.workspace.packageManager ?? "npm";
1831
1883
  return processPlan(ctx, "package-audit", manager, ["audit", "--json"], {
@@ -2261,13 +2313,28 @@ var csharpProfile = {
2261
2313
  }),
2262
2314
  "package-add": async (ctx) => {
2263
2315
  const names = packageNames(ctx);
2264
- return names.length === 0 ? unavailable(ctx, "package-add", "At least one NuGet package is required.") : processPlan(ctx, "package-add", "dotnet", ["add", "package", ...names], {
2265
- parser: "dotnet-package",
2266
- reason: "Add validated NuGet packages.",
2267
- mutating: true,
2268
- network: true,
2269
- executesProjectCode: true
2270
- });
2316
+ const [spec] = names;
2317
+ const versionAt = spec?.lastIndexOf("@") ?? -1;
2318
+ const packageName = versionAt > 0 ? spec?.slice(0, versionAt) : spec;
2319
+ const packageVersion = versionAt > 0 ? spec?.slice(versionAt + 1) : void 0;
2320
+ return names.length === 0 ? unavailable(ctx, "package-add", "At least one NuGet package is required.") : names.length > 1 ? unavailable(ctx, "package-add", "NuGet package changes run one package at a time.") : processPlan(
2321
+ ctx,
2322
+ "package-add",
2323
+ "dotnet",
2324
+ [
2325
+ "add",
2326
+ "package",
2327
+ packageName ?? "",
2328
+ ...packageVersion ? ["--version", packageVersion] : []
2329
+ ],
2330
+ {
2331
+ parser: "dotnet-package",
2332
+ reason: "Add validated NuGet packages.",
2333
+ mutating: true,
2334
+ network: true,
2335
+ executesProjectCode: true
2336
+ }
2337
+ );
2271
2338
  },
2272
2339
  "package-remove": async (ctx) => {
2273
2340
  const names = packageNames(ctx);
@@ -3120,6 +3187,7 @@ var MAX_ARGUMENT_LENGTH = 4096;
3120
3187
  var PACKAGE_NAME_RE = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+(?:@[a-z0-9*+._~^<>=|-]+)?$/i;
3121
3188
  var COMPOSER_PACKAGE_RE = /^[a-z0-9_.-]+\/[a-z0-9_.-]+(?::[a-z0-9*+._~^<>=|-]+)?$/i;
3122
3189
  var GO_MODULE_RE = /^(?:[a-z0-9.-]+\.)+[a-z0-9.-]+\/[a-z0-9._~+/@-]+$/i;
3190
+ var PYTHON_PACKAGE_RE = /^[a-z0-9._-]+(?:\[[a-z0-9._,-]+\])?==[a-z0-9*+._!~-]+$/i;
3123
3191
  async function planLanguageOperation(options) {
3124
3192
  validateOperationOptions(options.operation, options.operationOptions?.packages);
3125
3193
  const detection = await detectLanguageWorkspaces(options);
@@ -3303,7 +3371,7 @@ function validateOperationOptions(operation, packages) {
3303
3371
  if (value.startsWith(".") || value.startsWith("/") || /^[A-Za-z]:/.test(value) || value.includes("://")) {
3304
3372
  throw new Error(`Package paths and URLs are not supported: "${value}"`);
3305
3373
  }
3306
- if (!PACKAGE_NAME_RE.test(value) && !COMPOSER_PACKAGE_RE.test(value) && !GO_MODULE_RE.test(value)) {
3374
+ if (!PACKAGE_NAME_RE.test(value) && !COMPOSER_PACKAGE_RE.test(value) && !GO_MODULE_RE.test(value) && !PYTHON_PACKAGE_RE.test(value)) {
3307
3375
  throw new Error(`Invalid package identifier "${value}"`);
3308
3376
  }
3309
3377
  }