agent-nuvira 3.3.7 → 3.3.9
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 +57 -50
- package/dist/agents/agents/planner.d.ts.map +1 -1
- package/dist/agents/agents/planner.js +41 -0
- package/dist/agents/agents/planner.js.map +1 -1
- package/dist/agents/agents/reasoner.d.ts.map +1 -1
- package/dist/agents/agents/reasoner.js +6 -0
- package/dist/agents/agents/reasoner.js.map +1 -1
- package/dist/agents/agents/runner.d.ts +6 -0
- package/dist/agents/agents/runner.d.ts.map +1 -1
- package/dist/agents/agents/runner.js +82 -5
- package/dist/agents/agents/runner.js.map +1 -1
- package/dist/agents/agents/writer-tool-calling.d.ts.map +1 -1
- package/dist/agents/agents/writer-tool-calling.js +5 -2
- package/dist/agents/agents/writer-tool-calling.js.map +1 -1
- package/dist/agents/agents/writer.d.ts.map +1 -1
- package/dist/agents/agents/writer.js +8 -4
- package/dist/agents/agents/writer.js.map +1 -1
- package/dist/agents/fanout-scheduler.d.ts +72 -0
- package/dist/agents/fanout-scheduler.d.ts.map +1 -0
- package/dist/agents/fanout-scheduler.js +100 -0
- package/dist/agents/fanout-scheduler.js.map +1 -0
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +30 -1
- package/dist/agents/orchestrator.js.map +1 -1
- package/dist/agents/plan-quality.d.ts +58 -0
- package/dist/agents/plan-quality.d.ts.map +1 -0
- package/dist/agents/plan-quality.js +152 -0
- package/dist/agents/plan-quality.js.map +1 -0
- package/dist/agents/prompt-assembly.d.ts +8 -0
- package/dist/agents/prompt-assembly.d.ts.map +1 -1
- package/dist/agents/prompt-assembly.js +18 -0
- package/dist/agents/prompt-assembly.js.map +1 -1
- package/dist/agents/step-handoff.d.ts +12 -2
- package/dist/agents/step-handoff.d.ts.map +1 -1
- package/dist/agents/step-handoff.js +65 -8
- package/dist/agents/step-handoff.js.map +1 -1
- package/dist/agents/tool-calling-agent.d.ts.map +1 -1
- package/dist/agents/tool-calling-agent.js +18 -0
- package/dist/agents/tool-calling-agent.js.map +1 -1
- package/dist/cli/cache.d.ts.map +1 -1
- package/dist/cli/cache.js +34 -4
- package/dist/cli/cache.js.map +1 -1
- package/dist/cli/chat.d.ts +6 -0
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +79 -18
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/cli-program.d.ts.map +1 -1
- package/dist/cli/cli-program.js +6 -0
- package/dist/cli/cli-program.js.map +1 -1
- package/dist/cli/config.d.ts +10 -0
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +179 -1
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/continuity.d.ts +61 -0
- package/dist/cli/continuity.d.ts.map +1 -0
- package/dist/cli/continuity.js +112 -0
- package/dist/cli/continuity.js.map +1 -0
- package/dist/cli/dashboard.d.ts +3 -1
- package/dist/cli/dashboard.d.ts.map +1 -1
- package/dist/cli/dashboard.js +5 -16
- package/dist/cli/dashboard.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +48 -1
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/execute.d.ts +8 -0
- package/dist/cli/execute.d.ts.map +1 -1
- package/dist/cli/execute.js +34 -1
- package/dist/cli/execute.js.map +1 -1
- package/dist/cli/loop-executor.d.ts +24 -0
- package/dist/cli/loop-executor.d.ts.map +1 -1
- package/dist/cli/loop-executor.js +134 -13
- package/dist/cli/loop-executor.js.map +1 -1
- package/dist/cli/website.d.ts +25 -0
- package/dist/cli/website.d.ts.map +1 -0
- package/dist/cli/website.js +58 -0
- package/dist/cli/website.js.map +1 -0
- package/dist/config/manager.d.ts.map +1 -1
- package/dist/config/manager.js +35 -0
- package/dist/config/manager.js.map +1 -1
- package/dist/config/process-env.d.ts.map +1 -1
- package/dist/config/process-env.js +20 -0
- package/dist/config/process-env.js.map +1 -1
- package/dist/config/provider-env.d.ts +2 -1
- package/dist/config/provider-env.d.ts.map +1 -1
- package/dist/config/provider-env.js +19 -2
- package/dist/config/provider-env.js.map +1 -1
- package/dist/config/service-catalog.d.ts +81 -0
- package/dist/config/service-catalog.d.ts.map +1 -0
- package/dist/config/service-catalog.js +286 -0
- package/dist/config/service-catalog.js.map +1 -0
- package/dist/config/service-probe.d.ts +27 -0
- package/dist/config/service-probe.d.ts.map +1 -0
- package/dist/config/service-probe.js +104 -0
- package/dist/config/service-probe.js.map +1 -0
- package/dist/config/types.d.ts +63 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/context/cache.d.ts +46 -2
- package/dist/context/cache.d.ts.map +1 -1
- package/dist/context/cache.js +85 -7
- package/dist/context/cache.js.map +1 -1
- package/dist/findings/verdicts.d.ts +59 -0
- package/dist/findings/verdicts.d.ts.map +1 -1
- package/dist/findings/verdicts.js +117 -0
- package/dist/findings/verdicts.js.map +1 -1
- package/dist/forwarded.d.ts +2 -0
- package/dist/forwarded.d.ts.map +1 -0
- package/dist/forwarded.js +2 -0
- package/dist/forwarded.js.map +1 -0
- package/dist/gateway/registry.d.ts.map +1 -1
- package/dist/gateway/registry.js +9 -0
- package/dist/gateway/registry.js.map +1 -1
- package/dist/learning/auto-router.d.ts +30 -0
- package/dist/learning/auto-router.d.ts.map +1 -1
- package/dist/learning/auto-router.js +69 -12
- package/dist/learning/auto-router.js.map +1 -1
- package/dist/learning/context-assembly.d.ts +37 -0
- package/dist/learning/context-assembly.d.ts.map +1 -0
- package/dist/learning/context-assembly.js +63 -0
- package/dist/learning/context-assembly.js.map +1 -0
- package/dist/learning/reasoning-trace.d.ts +26 -5
- package/dist/learning/reasoning-trace.d.ts.map +1 -1
- package/dist/learning/reasoning-trace.js +21 -1
- package/dist/learning/reasoning-trace.js.map +1 -1
- package/dist/learning/session-digest.d.ts +78 -0
- package/dist/learning/session-digest.d.ts.map +1 -0
- package/dist/learning/session-digest.js +185 -0
- package/dist/learning/session-digest.js.map +1 -0
- package/dist/learning/session-recall.d.ts +135 -0
- package/dist/learning/session-recall.d.ts.map +1 -0
- package/dist/learning/session-recall.js +305 -0
- package/dist/learning/session-recall.js.map +1 -0
- package/dist/learning/session-store.d.ts +172 -0
- package/dist/learning/session-store.d.ts.map +1 -0
- package/dist/learning/session-store.js +424 -0
- package/dist/learning/session-store.js.map +1 -0
- package/dist/learning/step-checkpoint.d.ts +28 -0
- package/dist/learning/step-checkpoint.d.ts.map +1 -1
- package/dist/learning/step-checkpoint.js +90 -6
- package/dist/learning/step-checkpoint.js.map +1 -1
- package/dist/learning/working-state.d.ts +19 -0
- package/dist/learning/working-state.d.ts.map +1 -1
- package/dist/learning/working-state.js +34 -1
- package/dist/learning/working-state.js.map +1 -1
- package/dist/parity/drivers.d.ts.map +1 -1
- package/dist/parity/drivers.js +29 -0
- package/dist/parity/drivers.js.map +1 -1
- package/dist/parity/wire-fixtures.d.ts +88 -0
- package/dist/parity/wire-fixtures.d.ts.map +1 -0
- package/dist/parity/wire-fixtures.js +405 -0
- package/dist/parity/wire-fixtures.js.map +1 -0
- package/dist/tools/artifact-append.d.ts +23 -0
- package/dist/tools/artifact-append.d.ts.map +1 -1
- package/dist/tools/artifact-append.js +28 -0
- package/dist/tools/artifact-append.js.map +1 -1
- package/dist/tools/ask-user.d.ts +5 -0
- package/dist/tools/ask-user.d.ts.map +1 -1
- package/dist/tools/ask-user.js +51 -5
- package/dist/tools/ask-user.js.map +1 -1
- package/dist/tools/child-agent-entry.js +1 -0
- package/dist/tools/child-agent-entry.js.map +1 -1
- package/dist/tools/child-agent-runtime.d.ts +7 -0
- package/dist/tools/child-agent-runtime.d.ts.map +1 -1
- package/dist/tools/child-agent-runtime.js +116 -6
- package/dist/tools/child-agent-runtime.js.map +1 -1
- package/dist/tools/child-agent-worker.d.ts +15 -0
- package/dist/tools/child-agent-worker.d.ts.map +1 -0
- package/dist/tools/child-agent-worker.js.map +1 -0
- package/dist/tools/coding-tools.d.ts.map +1 -1
- package/dist/tools/coding-tools.js +11 -0
- package/dist/tools/coding-tools.js.map +1 -1
- package/dist/tools/finding-tool.d.ts +6 -1
- package/dist/tools/finding-tool.d.ts.map +1 -1
- package/dist/tools/finding-tool.js +15 -2
- package/dist/tools/finding-tool.js.map +1 -1
- package/dist/tools/followup-utils.d.ts +35 -0
- package/dist/tools/followup-utils.d.ts.map +1 -1
- package/dist/tools/followup-utils.js +36 -0
- package/dist/tools/followup-utils.js.map +1 -1
- package/dist/tools/loop-project-context.d.ts +4 -1
- package/dist/tools/loop-project-context.d.ts.map +1 -1
- package/dist/tools/loop-project-context.js +48 -1
- package/dist/tools/loop-project-context.js.map +1 -1
- package/dist/tools/loop-skill-hint.d.ts.map +1 -1
- package/dist/tools/loop-skill-hint.js +7 -0
- package/dist/tools/loop-skill-hint.js.map +1 -1
- package/dist/tools/modality/image-gen.d.ts +25 -6
- package/dist/tools/modality/image-gen.d.ts.map +1 -1
- package/dist/tools/modality/image-gen.js +46 -27
- package/dist/tools/modality/image-gen.js.map +1 -1
- package/dist/tools/modality/image-providers.d.ts +71 -0
- package/dist/tools/modality/image-providers.d.ts.map +1 -0
- package/dist/tools/modality/image-providers.js +277 -0
- package/dist/tools/modality/image-providers.js.map +1 -0
- package/dist/tools/registry.d.ts +10 -1
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +35 -8
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/run-cli.d.ts.map +1 -1
- package/dist/tools/run-cli.js +39 -1
- package/dist/tools/run-cli.js.map +1 -1
- package/dist/tools/run-terminal.d.ts.map +1 -1
- package/dist/tools/run-terminal.js +50 -6
- package/dist/tools/run-terminal.js.map +1 -1
- package/dist/tools/subagent-spawner.d.ts +8 -0
- package/dist/tools/subagent-spawner.d.ts.map +1 -1
- package/dist/tools/subagent-spawner.js +3 -0
- package/dist/tools/subagent-spawner.js.map +1 -1
- package/dist/tools/tool-loop.d.ts +55 -0
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +136 -0
- package/dist/tools/tool-loop.js.map +1 -1
- package/dist/tools/untrusted-content.d.ts +29 -0
- package/dist/tools/untrusted-content.d.ts.map +1 -0
- package/dist/tools/untrusted-content.js +53 -0
- package/dist/tools/untrusted-content.js.map +1 -0
- package/dist/tools/web-research.d.ts +76 -14
- package/dist/tools/web-research.d.ts.map +1 -1
- package/dist/tools/web-research.js +280 -35
- package/dist/tools/web-research.js.map +1 -1
- package/dist/utils/effect-verification.d.ts +115 -0
- package/dist/utils/effect-verification.d.ts.map +1 -0
- package/dist/utils/effect-verification.js +337 -0
- package/dist/utils/effect-verification.js.map +1 -0
- package/dist/utils/open-url.d.ts +16 -0
- package/dist/utils/open-url.d.ts.map +1 -0
- package/dist/utils/open-url.js +32 -0
- package/dist/utils/open-url.js.map +1 -0
- package/dist/utils/project-env.d.ts +146 -0
- package/dist/utils/project-env.d.ts.map +1 -0
- package/dist/utils/project-env.js +584 -0
- package/dist/utils/project-env.js.map +1 -0
- package/dist/utils/shell.d.ts +7 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +2 -0
- package/dist/utils/shell.js.map +1 -1
- package/dist/web-dashboard/chat-console.d.ts +2 -0
- package/dist/web-dashboard/chat-console.d.ts.map +1 -1
- package/dist/web-dashboard/chat-console.js +7 -0
- package/dist/web-dashboard/chat-console.js.map +1 -1
- package/dist/web-dashboard/server.d.ts +3 -1
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +534 -8
- package/dist/web-dashboard/server.js.map +1 -1
- package/dist/web-dashboard/src/types.d.ts +150 -1
- package/dist/web-dashboard/src/types.d.ts.map +1 -1
- package/dist/web-dashboard/workspace-guard.d.ts +40 -0
- package/dist/web-dashboard/workspace-guard.d.ts.map +1 -0
- package/dist/web-dashboard/workspace-guard.js +92 -0
- package/dist/web-dashboard/workspace-guard.js.map +1 -0
- package/package.json +4 -1
- package/src/web-dashboard/public/assets/index-Beportyl.js +207 -0
- package/src/web-dashboard/public/assets/index-Beportyl.js.map +1 -0
- package/src/web-dashboard/public/assets/index-gtQyg9nm.css +1 -0
- package/src/web-dashboard/public/index.html +2 -2
- package/src/web-dashboard/public/assets/index-D1YFCcIZ.js +0 -207
- package/src/web-dashboard/public/assets/index-D1YFCcIZ.js.map +0 -1
- package/src/web-dashboard/public/assets/index-jkW5qcf-.css +0 -1
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project interpreter canonicalization + pre-run environment guard.
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS EXISTS (the live Aukat_check failure):
|
|
5
|
+
* One chat session built a macOS app by running `python3 -m venv venv` and
|
|
6
|
+
* `pip install …` against the SYSTEM interpreter, while a project virtualenv sat
|
|
7
|
+
* in the same directory. A later rebuild therefore used an interpreter that did
|
|
8
|
+
* not have the project's own dependencies, produced an app that crashed with
|
|
9
|
+
* `ModuleNotFoundError: No module named 'PyQt6'`, and the run still reported
|
|
10
|
+
* success. The root cause was not a missing dependency — it was that NOTHING
|
|
11
|
+
* pinned "which interpreter is this project's" for the run, so each command
|
|
12
|
+
* guessed and the guesses disagreed.
|
|
13
|
+
*
|
|
14
|
+
* This module makes the guess unnecessary, deterministically and LLM-free:
|
|
15
|
+
*
|
|
16
|
+
* 1. DISCOVER — find the project's virtualenv (`.venv` preferred, then
|
|
17
|
+
* `venv`/`env`), walking up a bounded number of parent directories.
|
|
18
|
+
* 2. PIN — remember it for the whole process (keyed by directory), so every
|
|
19
|
+
* command in the run sees the SAME interpreter.
|
|
20
|
+
* 3. APPLY — prepend its `bin/` to PATH and set `VIRTUAL_ENV`, so a bare
|
|
21
|
+
* `python`/`pip`/`pyinstaller` resolves to the project env.
|
|
22
|
+
* 4. GUARD — refuse the two mistakes that caused the failure: installing
|
|
23
|
+
* Python packages into an interpreter OUTSIDE the project venv, and
|
|
24
|
+
* building/running with an interpreter that LACKS the project's declared
|
|
25
|
+
* dependencies.
|
|
26
|
+
*
|
|
27
|
+
* All checks are best-effort: a probe failure reports, it never breaks a run.
|
|
28
|
+
* `NUVIRA_ENV_GUARD=off` disables the refusals (the escape hatch a deployment
|
|
29
|
+
* with a deliberate system-Python setup needs).
|
|
30
|
+
*/
|
|
31
|
+
import { spawnSync } from 'node:child_process';
|
|
32
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
33
|
+
import { delimiter, dirname, join, resolve } from 'node:path';
|
|
34
|
+
/** Where the project marker files that describe Python deps live. */
|
|
35
|
+
const PYTHON_MANIFESTS = [
|
|
36
|
+
'requirements.txt',
|
|
37
|
+
'pyproject.toml',
|
|
38
|
+
'setup.py',
|
|
39
|
+
'setup.cfg',
|
|
40
|
+
'Pipfile',
|
|
41
|
+
'Pipfile.lock',
|
|
42
|
+
'poetry.lock',
|
|
43
|
+
];
|
|
44
|
+
/** Names that appear in a dependency manifest but are not distributions. */
|
|
45
|
+
const NON_DISTRIBUTION_NAMES = new Set([
|
|
46
|
+
'python',
|
|
47
|
+
'python_version',
|
|
48
|
+
'python_full_version',
|
|
49
|
+
'requires-python',
|
|
50
|
+
'requires_python',
|
|
51
|
+
]);
|
|
52
|
+
/**
|
|
53
|
+
* Candidate virtualenv directory names, in PREFERENCE order. `.venv` first
|
|
54
|
+
* because it is the modern convention (and the one a tool should create), and
|
|
55
|
+
* a project that has drifted into two envs should converge on one.
|
|
56
|
+
*/
|
|
57
|
+
const VENV_DIR_NAMES = ['.venv', 'venv', 'env', '.virtualenv', 'virtualenv'];
|
|
58
|
+
/** How many parent directories to search for a project venv. */
|
|
59
|
+
const MAX_PARENT_SEARCH = 3;
|
|
60
|
+
/** Is `dir` a Python virtualenv directory? */
|
|
61
|
+
function isVenvDir(dir) {
|
|
62
|
+
try {
|
|
63
|
+
if (!existsSync(dir) || !statSync(dir).isDirectory())
|
|
64
|
+
return false;
|
|
65
|
+
// Python 3 venvs carry pyvenv.cfg; older/edge cases still have an activate script.
|
|
66
|
+
if (existsSync(join(dir, 'pyvenv.cfg')))
|
|
67
|
+
return true;
|
|
68
|
+
return (existsSync(join(dir, 'bin', 'activate')) ||
|
|
69
|
+
existsSync(join(dir, 'Scripts', 'activate.bat')));
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** The interpreter path inside a venv dir, or null when none is present. */
|
|
76
|
+
function interpreterIn(dir, binDir) {
|
|
77
|
+
const candidates = binDir === 'Scripts'
|
|
78
|
+
? [join(dir, 'Scripts', 'python.exe')]
|
|
79
|
+
: [join(dir, 'bin', 'python'), join(dir, 'bin', 'python3')];
|
|
80
|
+
for (const p of candidates) {
|
|
81
|
+
if (existsSync(p))
|
|
82
|
+
return p;
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Find the project's virtualenv, starting at `startDir` and walking up a
|
|
88
|
+
* bounded number of parents (nearest wins, so a monorepo package's own env
|
|
89
|
+
* beats the repo root's).
|
|
90
|
+
*/
|
|
91
|
+
export function findProjectVenv(startDir) {
|
|
92
|
+
let dir;
|
|
93
|
+
try {
|
|
94
|
+
dir = resolve(startDir);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
for (let depth = 0; depth <= MAX_PARENT_SEARCH; depth++) {
|
|
100
|
+
for (const name of VENV_DIR_NAMES) {
|
|
101
|
+
const candidate = join(dir, name);
|
|
102
|
+
if (!isVenvDir(candidate))
|
|
103
|
+
continue;
|
|
104
|
+
const binDir = existsSync(join(candidate, 'Scripts')) ? 'Scripts' : 'bin';
|
|
105
|
+
const python = interpreterIn(candidate, binDir);
|
|
106
|
+
if (python)
|
|
107
|
+
return { dir: candidate, python, binDir: join(candidate, binDir) };
|
|
108
|
+
}
|
|
109
|
+
const parent = dirname(dir);
|
|
110
|
+
if (parent === dir)
|
|
111
|
+
break;
|
|
112
|
+
dir = parent;
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* The pinned interpreter per directory, for the lifetime of the process.
|
|
118
|
+
*
|
|
119
|
+
* "Pin it for the whole run" is the whole point: without this, two commands in
|
|
120
|
+
* the same turn can resolve different interpreters (which is exactly how one
|
|
121
|
+
* session created `venv` and then built with `.venv`). Keyed by the directory
|
|
122
|
+
* the command runs in, so different projects in one process stay separate.
|
|
123
|
+
*/
|
|
124
|
+
const PINNED = new Map();
|
|
125
|
+
/** The project venv for `dir`, discovered once and reused for the run. */
|
|
126
|
+
export function getPinnedProjectVenv(dir) {
|
|
127
|
+
let key;
|
|
128
|
+
try {
|
|
129
|
+
key = resolve(dir);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
if (PINNED.has(key))
|
|
135
|
+
return PINNED.get(key) ?? null;
|
|
136
|
+
const found = findProjectVenv(key);
|
|
137
|
+
PINNED.set(key, found);
|
|
138
|
+
return found;
|
|
139
|
+
}
|
|
140
|
+
/** Forget pinned interpreters (tests; also after creating a venv mid-run). */
|
|
141
|
+
export function clearPinnedProjectVenv() {
|
|
142
|
+
PINNED.clear();
|
|
143
|
+
}
|
|
144
|
+
/** Name of the venv the sandbox creates when a project has none. */
|
|
145
|
+
export const SANDBOX_VENV_NAME = '.venv';
|
|
146
|
+
/**
|
|
147
|
+
* Provision a project-scoped virtualenv (`C3` install sandbox).
|
|
148
|
+
*
|
|
149
|
+
* The live failure's 4th finding: a project-scoped fix mutated the machine's
|
|
150
|
+
* GLOBAL Python. Refusing such installs protects the machine but blocks the
|
|
151
|
+
* work; the better answer is to give the install a sandbox to land in. When no
|
|
152
|
+
* project venv exists, create `.venv` from the interpreter on PATH, PIN it for
|
|
153
|
+
* the run, and hand it back — so the following `pip install` populates the
|
|
154
|
+
* project env and the global interpreter is never touched.
|
|
155
|
+
*
|
|
156
|
+
* Returns null when the venv cannot be created (no base interpreter, or venv
|
|
157
|
+
* creation failed) — the caller then refuses rather than falling back to a
|
|
158
|
+
* global install.
|
|
159
|
+
*/
|
|
160
|
+
export function ensureProjectVenv(dir) {
|
|
161
|
+
const existing = getPinnedProjectVenv(dir);
|
|
162
|
+
if (existing)
|
|
163
|
+
return existing;
|
|
164
|
+
const base = interpreterOnPath();
|
|
165
|
+
if (!base)
|
|
166
|
+
return null;
|
|
167
|
+
let key;
|
|
168
|
+
try {
|
|
169
|
+
key = resolve(dir);
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
const venvDir = join(key, SANDBOX_VENV_NAME);
|
|
175
|
+
try {
|
|
176
|
+
const res = spawnSync(base, ['-m', 'venv', venvDir], {
|
|
177
|
+
encoding: 'utf-8',
|
|
178
|
+
timeout: 120_000,
|
|
179
|
+
windowsHide: true,
|
|
180
|
+
});
|
|
181
|
+
if (res.error || res.status !== 0)
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
const venv = findProjectVenv(key);
|
|
188
|
+
if (!venv || !venv.python)
|
|
189
|
+
return null;
|
|
190
|
+
PINNED.set(key, venv);
|
|
191
|
+
return venv;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Apply the pinned interpreter to a command's environment: prepend its `bin/`
|
|
195
|
+
* to PATH and set `VIRTUAL_ENV`, so a bare `python`/`pip`/`pyinstaller`
|
|
196
|
+
* resolves to the project env instead of whatever the shell would have found.
|
|
197
|
+
* A no-op when there is no venv (the environment is returned unchanged).
|
|
198
|
+
*/
|
|
199
|
+
export function applyProjectEnvironment(env, venv) {
|
|
200
|
+
if (!venv)
|
|
201
|
+
return env;
|
|
202
|
+
const current = env.PATH ?? '';
|
|
203
|
+
// A venv already on PATH is left alone; otherwise it goes first so it wins.
|
|
204
|
+
const parts = current.split(delimiter).filter(Boolean);
|
|
205
|
+
if (!parts.includes(venv.binDir))
|
|
206
|
+
parts.unshift(venv.binDir);
|
|
207
|
+
return {
|
|
208
|
+
...env,
|
|
209
|
+
PATH: parts.join(delimiter),
|
|
210
|
+
VIRTUAL_ENV: venv.dir,
|
|
211
|
+
// A VIRTUAL_ENV without a matching interpreter can confuse sub-tools.
|
|
212
|
+
PYTHONHOME: undefined,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Parse the distribution names a project declares in `requirements.txt`.
|
|
217
|
+
*
|
|
218
|
+
* Deliberately narrow and text-based (no TOML/pip dependency): it keeps only
|
|
219
|
+
* the name before any version specifier or environment marker, skips flags
|
|
220
|
+
* (`-r`, `-e`, `--index-url`), comments and blank lines, and follows a `-r`
|
|
221
|
+
* include one level deep. A name it cannot read is skipped rather than
|
|
222
|
+
* guessed — the guard must never invent a requirement the project did not ask
|
|
223
|
+
* for.
|
|
224
|
+
*/
|
|
225
|
+
function requirementNamesFromRequirementsTxt(text) {
|
|
226
|
+
const names = [];
|
|
227
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
228
|
+
const line = raw.trim();
|
|
229
|
+
if (!line || line.startsWith('#') || line.startsWith('-'))
|
|
230
|
+
continue;
|
|
231
|
+
// `pkg[extra]==1.2 ; python_version>'3.8'` -> `pkg`
|
|
232
|
+
const match = line.match(/^([A-Za-z0-9][A-Za-z0-9._-]*)/);
|
|
233
|
+
if (match)
|
|
234
|
+
names.push(match[1]);
|
|
235
|
+
}
|
|
236
|
+
return names;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Distribution names declared as KEYS of one or more TOML tables, selected by
|
|
240
|
+
* a section predicate. Handles the `[tool.poetry.dependencies]` shape
|
|
241
|
+
* (`requests = "^2.31"` / `requests = { version = "…" }`) and poetry's newer
|
|
242
|
+
* `[tool.poetry.group.<name>.dependencies]` tables. A key that names the
|
|
243
|
+
* interpreter (`python`) or an environment selector is skipped — it is not a
|
|
244
|
+
* distribution the guard should demand.
|
|
245
|
+
*
|
|
246
|
+
* Text-based on purpose: the guard must not pull a TOML parser into the hot
|
|
247
|
+
* path, and an unreadable line is skipped rather than guessed.
|
|
248
|
+
*/
|
|
249
|
+
function requirementNamesFromTomlSections(text, isDependencySection) {
|
|
250
|
+
const names = [];
|
|
251
|
+
let inSection = false;
|
|
252
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
253
|
+
const line = raw.trim();
|
|
254
|
+
const section = line.match(/^\[([^\]]+)\]/);
|
|
255
|
+
if (section) {
|
|
256
|
+
inSection = isDependencySection(section[1].trim());
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (!inSection || !line || line.startsWith('#'))
|
|
260
|
+
continue;
|
|
261
|
+
const match = line.match(/^([A-Za-z0-9][A-Za-z0-9._-]*)\s*=/);
|
|
262
|
+
if (match && !NON_DISTRIBUTION_NAMES.has(match[1].toLowerCase()))
|
|
263
|
+
names.push(match[1]);
|
|
264
|
+
}
|
|
265
|
+
return names;
|
|
266
|
+
}
|
|
267
|
+
/** Is this a poetry dependency table? (`tool.poetry.dependencies`, dev, groups) */
|
|
268
|
+
function isPoetryDependencySection(section) {
|
|
269
|
+
return (section === 'tool.poetry.dependencies' ||
|
|
270
|
+
section === 'tool.poetry.dev-dependencies' ||
|
|
271
|
+
/^tool\.poetry\.group\.[^.]+\.dependencies$/.test(section));
|
|
272
|
+
}
|
|
273
|
+
/** Is this a pipenv table? (`packages`, `dev-packages`) */
|
|
274
|
+
function isPipfileDependencySection(section) {
|
|
275
|
+
return section === 'packages' || section === 'dev-packages';
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Distribution names from a `Pipfile` (`[packages]` + `[dev-packages]`).
|
|
279
|
+
*/
|
|
280
|
+
function requirementNamesFromPipfile(text) {
|
|
281
|
+
const names = [];
|
|
282
|
+
let inSection = false;
|
|
283
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
284
|
+
const line = raw.trim();
|
|
285
|
+
const section = line.match(/^\[([^\]]+)\]/);
|
|
286
|
+
if (section) {
|
|
287
|
+
inSection = isPipfileDependencySection(section[1].trim());
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
if (!inSection || !line || line.startsWith('#'))
|
|
291
|
+
continue;
|
|
292
|
+
const match = line.match(/^([A-Za-z0-9][A-Za-z0-9._-]*)\s*=/);
|
|
293
|
+
if (match && !NON_DISTRIBUTION_NAMES.has(match[1].toLowerCase()))
|
|
294
|
+
names.push(match[1]);
|
|
295
|
+
}
|
|
296
|
+
return names;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Distribution names from a `Pipfile.lock` (JSON): the `default` and
|
|
300
|
+
* `develop` maps. Used only as a fallback when no `Pipfile` is present.
|
|
301
|
+
*/
|
|
302
|
+
function requirementNamesFromPipfileLock(text) {
|
|
303
|
+
const names = [];
|
|
304
|
+
try {
|
|
305
|
+
const parsed = JSON.parse(text);
|
|
306
|
+
for (const key of ['default', 'develop']) {
|
|
307
|
+
const group = parsed[key];
|
|
308
|
+
if (group && typeof group === 'object')
|
|
309
|
+
names.push(...Object.keys(group));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
/* best-effort */
|
|
314
|
+
}
|
|
315
|
+
return names;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* The distribution names a project declares, from `requirements.txt`, a
|
|
319
|
+
* best-effort scan of `pyproject.toml` (PEP 621 `dependencies = [ … ]` AND
|
|
320
|
+
* poetry's `[tool.poetry.dependencies]` tables), and a `Pipfile`/`Pipfile.lock`
|
|
321
|
+
* (pipenv). Returns [] when there is nothing to check — the guard then does
|
|
322
|
+
* nothing.
|
|
323
|
+
*/
|
|
324
|
+
export function projectRequirementNames(projectDir) {
|
|
325
|
+
const names = new Set();
|
|
326
|
+
const reqPath = join(projectDir, 'requirements.txt');
|
|
327
|
+
try {
|
|
328
|
+
if (existsSync(reqPath)) {
|
|
329
|
+
for (const n of requirementNamesFromRequirementsTxt(readFileSync(reqPath, 'utf-8'))) {
|
|
330
|
+
names.add(n);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
/* best-effort */
|
|
336
|
+
}
|
|
337
|
+
const pyproject = join(projectDir, 'pyproject.toml');
|
|
338
|
+
try {
|
|
339
|
+
if (existsSync(pyproject)) {
|
|
340
|
+
const text = readFileSync(pyproject, 'utf-8');
|
|
341
|
+
// PEP 621 / poetry 2.x: `dependencies = [ "a", "b" ]`
|
|
342
|
+
const block = text.match(/dependencies\s*=\s*\[([\s\S]*?)\]/);
|
|
343
|
+
if (block) {
|
|
344
|
+
for (const n of requirementNamesFromRequirementsTxt(block[1].replace(/["',]/g, '\n'))) {
|
|
345
|
+
names.add(n);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// poetry 1.x: `[tool.poetry.dependencies]` / groups / dev-dependencies
|
|
349
|
+
for (const n of requirementNamesFromTomlSections(text, isPoetryDependencySection)) {
|
|
350
|
+
names.add(n);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
/* best-effort */
|
|
356
|
+
}
|
|
357
|
+
const pipfile = join(projectDir, 'Pipfile');
|
|
358
|
+
try {
|
|
359
|
+
if (existsSync(pipfile)) {
|
|
360
|
+
for (const n of requirementNamesFromPipfile(readFileSync(pipfile, 'utf-8')))
|
|
361
|
+
names.add(n);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
const lock = join(projectDir, 'Pipfile.lock');
|
|
365
|
+
if (existsSync(lock)) {
|
|
366
|
+
for (const n of requirementNamesFromPipfileLock(readFileSync(lock, 'utf-8')))
|
|
367
|
+
names.add(n);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
/* best-effort */
|
|
373
|
+
}
|
|
374
|
+
return [...names];
|
|
375
|
+
}
|
|
376
|
+
/** Does this directory look like it declares Python dependencies? */
|
|
377
|
+
export function hasPythonManifest(dir) {
|
|
378
|
+
return PYTHON_MANIFESTS.some((m) => existsSync(join(dir, m)));
|
|
379
|
+
}
|
|
380
|
+
// ─── Command classification ────────────────────────────────────────────────
|
|
381
|
+
/** Split a shell line into the separately-run pieces (the `&&`/`;`/`|` chain). */
|
|
382
|
+
function commandSegments(command) {
|
|
383
|
+
return command
|
|
384
|
+
.toLowerCase()
|
|
385
|
+
.split(/&&|;|\|\||\n|\|/)
|
|
386
|
+
.map((s) => s.trim())
|
|
387
|
+
.filter(Boolean);
|
|
388
|
+
}
|
|
389
|
+
const PYTHON_TOOLCHAIN_RE = /^(?:(?:sudo|env|command|time)\s+)*(?:[\w./-]*\/)?(python3?(?:\.\d+)?|pip3?|uv|pyinstaller|pytest|py\.test|uvicorn|gunicorn|flask|django-admin|poetry|pipenv|tox)\b/;
|
|
390
|
+
/**
|
|
391
|
+
* Does any segment of this command invoke the Python toolchain? (A bare
|
|
392
|
+
* `python`/`pip`/`pyinstaller`/`pytest`, or `python -m …`.)
|
|
393
|
+
*/
|
|
394
|
+
export function isPythonToolchainCommand(command) {
|
|
395
|
+
return commandSegments(command).some((s) => PYTHON_TOOLCHAIN_RE.test(s));
|
|
396
|
+
}
|
|
397
|
+
const PIP_INSTALL_RE = /^(?:(?:sudo|env|command|time)\s+)*(?:[\w./-]*\/)?(?:pip3?\s+install|python3?(?:\.\d+)?\s+-m\s+pip\s+install|uv\s+(?:pip\s+)?install|uv\s+add|poetry\s+(?:add|install)|pipenv\s+install)\b/;
|
|
398
|
+
/** Does any segment of this command install Python packages? */
|
|
399
|
+
export function isPythonInstallCommand(command) {
|
|
400
|
+
return commandSegments(command).some((s) => PIP_INSTALL_RE.test(s));
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Does the command name an absolute interpreter OUTSIDE the pinned venv
|
|
404
|
+
* (e.g. `/usr/local/bin/python3 -m pip install …`)? A bare `python3` does NOT
|
|
405
|
+
* count: with the venv on PATH it resolves to the project env, which is the
|
|
406
|
+
* outcome we want.
|
|
407
|
+
*/
|
|
408
|
+
export function targetsForeignInterpreter(command, venv) {
|
|
409
|
+
// `--user` installs into the user site, never the project env — foreign
|
|
410
|
+
// whether or not an absolute interpreter is also named.
|
|
411
|
+
if (/(?:^|\s)--user\b/.test(command))
|
|
412
|
+
return true;
|
|
413
|
+
const abs = command.match(/(?:^|\s)(\/[\w./-]*\/?(?:python3?(?:\.\d+)?|pip3?))\b/g) ?? [];
|
|
414
|
+
if (abs.length === 0)
|
|
415
|
+
return false;
|
|
416
|
+
if (!venv)
|
|
417
|
+
return true; // an absolute interpreter with no pinned venv is foreign by definition
|
|
418
|
+
return abs.some((token) => {
|
|
419
|
+
const path = token.trim();
|
|
420
|
+
return !path.startsWith(venv.binDir) && !path.startsWith(venv.dir);
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
/** Install packages the project declares, inside the given interpreter. */
|
|
424
|
+
const PROBE_SCRIPT = [
|
|
425
|
+
'import sys, json, importlib.metadata as md',
|
|
426
|
+
'reqs = json.loads(sys.argv[1])',
|
|
427
|
+
'missing = []',
|
|
428
|
+
'for r in reqs:',
|
|
429
|
+
' ok = False',
|
|
430
|
+
" for c in (r, r.replace('_','-'), r.replace('.','-')):",
|
|
431
|
+
' try:',
|
|
432
|
+
' md.version(c); ok = True; break',
|
|
433
|
+
' except Exception:',
|
|
434
|
+
' pass',
|
|
435
|
+
' if not ok:',
|
|
436
|
+
' missing.append(r)',
|
|
437
|
+
'print(json.dumps(missing))',
|
|
438
|
+
].join('\n');
|
|
439
|
+
/**
|
|
440
|
+
* Which declared distributions are NOT installed in `python`?
|
|
441
|
+
* A probe that fails to run returns [] — an unavailable interpreter is not
|
|
442
|
+
* evidence that a dependency is missing, and the guard must never refuse on a
|
|
443
|
+
* guess.
|
|
444
|
+
*/
|
|
445
|
+
export const defaultEnvironmentProbe = (python, names) => {
|
|
446
|
+
if (names.length === 0)
|
|
447
|
+
return [];
|
|
448
|
+
try {
|
|
449
|
+
const res = spawnSync(python, ['-c', PROBE_SCRIPT, JSON.stringify(names)], {
|
|
450
|
+
encoding: 'utf-8',
|
|
451
|
+
timeout: 8000,
|
|
452
|
+
windowsHide: true,
|
|
453
|
+
});
|
|
454
|
+
if (res.error || res.status !== 0)
|
|
455
|
+
return [];
|
|
456
|
+
const parsed = JSON.parse((res.stdout ?? '').trim() || '[]');
|
|
457
|
+
return Array.isArray(parsed) ? parsed.map(String) : [];
|
|
458
|
+
}
|
|
459
|
+
catch {
|
|
460
|
+
return [];
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
/** Memoize probes for the run, keyed by interpreter + the requirement set. */
|
|
464
|
+
const PROBE_CACHE = new Map();
|
|
465
|
+
/** The interpreter a bare `python`/`python3` would resolve to on PATH. */
|
|
466
|
+
function interpreterOnPath() {
|
|
467
|
+
try {
|
|
468
|
+
const res = spawnSync(process.platform === 'win32' ? 'where' : 'which', ['python3'], {
|
|
469
|
+
encoding: 'utf-8',
|
|
470
|
+
timeout: 4000,
|
|
471
|
+
windowsHide: true,
|
|
472
|
+
});
|
|
473
|
+
if (res.status !== 0)
|
|
474
|
+
return null;
|
|
475
|
+
const first = (res.stdout ?? '').split(/\r?\n/).map((s) => s.trim()).filter(Boolean)[0];
|
|
476
|
+
return first ?? null;
|
|
477
|
+
}
|
|
478
|
+
catch {
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
/** Is the guard disabled by the deployment? */
|
|
483
|
+
export function envGuardDisabled() {
|
|
484
|
+
const raw = (process.env.NUVIRA_ENV_GUARD ?? process.env.BUFF_ENV_GUARD ?? '').trim().toLowerCase();
|
|
485
|
+
return raw === 'off' || raw === '0' || raw === 'false' || raw === 'no';
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Decide whether a command may run against the project's environment.
|
|
489
|
+
*
|
|
490
|
+
* Two refusals, both drawn from the live failure:
|
|
491
|
+
* 1. a Python PACKAGE INSTALL that would land outside the project venv (or
|
|
492
|
+
* with no venv at all while the project declares dependencies);
|
|
493
|
+
* 2. a BUILD/RUN with an interpreter that is missing the project's declared
|
|
494
|
+
* dependencies — the `PyQt6` case, caught before the build instead of
|
|
495
|
+
* after a successful-looking bundle.
|
|
496
|
+
* Everything else proceeds, with the pinned venv applied to the environment.
|
|
497
|
+
*/
|
|
498
|
+
export function guardCommandEnvironment(command, cwd, options = {}) {
|
|
499
|
+
if (envGuardDisabled())
|
|
500
|
+
return { action: 'not-applicable' };
|
|
501
|
+
if (!isPythonToolchainCommand(command))
|
|
502
|
+
return { action: 'not-applicable' };
|
|
503
|
+
let venv = getPinnedProjectVenv(cwd);
|
|
504
|
+
const names = projectRequirementNames(cwd);
|
|
505
|
+
if (isPythonInstallCommand(command)) {
|
|
506
|
+
if (targetsForeignInterpreter(command, venv)) {
|
|
507
|
+
return {
|
|
508
|
+
action: 'refuse',
|
|
509
|
+
reason: 'this install names an interpreter outside the project virtualenv',
|
|
510
|
+
hint: venv
|
|
511
|
+
? `Install into the project env instead: \`${venv.python} -m pip install …\` (or rely on the pinned PATH, which already points at ${venv.binDir}).`
|
|
512
|
+
: 'Create and use a project virtualenv first: `python3 -m venv .venv` then `.venv/bin/python -m pip install …` — never install project dependencies into the system interpreter.',
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
// ── C3: install sandbox ───────────────────────────────────────────────
|
|
516
|
+
// With no project venv, a `pip install` would mutate the interpreter on
|
|
517
|
+
// PATH — the machine's GLOBAL Python. Rather than merely refuse (which
|
|
518
|
+
// blocks the fix), provision a project-scoped `.venv`, PIN it, and run the
|
|
519
|
+
// install there. Only a provision failure falls back to refusal, so the
|
|
520
|
+
// global interpreter is never the target.
|
|
521
|
+
if (!venv) {
|
|
522
|
+
const provision = options.provision ?? ensureProjectVenv;
|
|
523
|
+
venv = provision(cwd);
|
|
524
|
+
if (!venv) {
|
|
525
|
+
return {
|
|
526
|
+
action: 'refuse',
|
|
527
|
+
reason: names.length > 0
|
|
528
|
+
? 'this project declares Python dependencies but has no virtualenv, and one could not be created, so the install would mutate the system interpreter'
|
|
529
|
+
: 'this install has no project virtualenv to land in, and one could not be created, so it would mutate the system interpreter',
|
|
530
|
+
hint: 'Create and use one yourself: `python3 -m venv .venv && .venv/bin/python -m pip install …` (this pins `.venv` for the rest of the run).',
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
return {
|
|
534
|
+
action: 'proceed',
|
|
535
|
+
venv,
|
|
536
|
+
note: `created a project venv ${venv.dir} and sandboxed the install there (the system interpreter is untouched)`,
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
return { action: 'proceed', venv, note: `installing into the project venv ${venv.dir}` };
|
|
540
|
+
}
|
|
541
|
+
// Build/run: the interpreter must actually have the project's dependencies.
|
|
542
|
+
const interpreter = venv?.python ?? interpreterOnPath();
|
|
543
|
+
if (interpreter && names.length > 0) {
|
|
544
|
+
const probe = options.probe ?? defaultEnvironmentProbe;
|
|
545
|
+
const cacheKey = `${interpreter}\u0000${names.join(',')}`;
|
|
546
|
+
let missing = PROBE_CACHE.get(cacheKey);
|
|
547
|
+
if (missing === undefined) {
|
|
548
|
+
missing = probe(interpreter, names);
|
|
549
|
+
PROBE_CACHE.set(cacheKey, missing);
|
|
550
|
+
}
|
|
551
|
+
if (missing.length > 0) {
|
|
552
|
+
const label = venv ? 'the project venv' : 'the interpreter on PATH';
|
|
553
|
+
return {
|
|
554
|
+
action: 'refuse',
|
|
555
|
+
reason: `${label} (${interpreter}) is missing ${missing.length} declared dependency(ies): ${missing.join(', ')}`,
|
|
556
|
+
hint: venv
|
|
557
|
+
? `Install them into the venv first: \`${venv.python} -m pip install -r requirements.txt\`, then re-run this command.`
|
|
558
|
+
: 'Create a project venv (`python3 -m venv .venv`), install the requirements into it, then re-run.',
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return { action: 'proceed', venv, note: venv ? `using the project venv ${venv.dir}` : undefined };
|
|
563
|
+
}
|
|
564
|
+
/** Forget memoized probes (tests; also after an install changes the env). */
|
|
565
|
+
export function clearEnvironmentProbeCache() {
|
|
566
|
+
PROBE_CACHE.clear();
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* A one-line description of the project interpreter for the ambient project
|
|
570
|
+
* context, so the model USES the pinned env instead of re-deriving it. '' when
|
|
571
|
+
* the directory declares nothing Python.
|
|
572
|
+
*/
|
|
573
|
+
export function describeProjectInterpreter(dir) {
|
|
574
|
+
try {
|
|
575
|
+
const venv = getPinnedProjectVenv(dir);
|
|
576
|
+
if (!venv)
|
|
577
|
+
return hasPythonManifest(dir) ? 'python: no project venv found (create `.venv`)' : '';
|
|
578
|
+
return `python: ${venv.python} (pinned for this project)`;
|
|
579
|
+
}
|
|
580
|
+
catch {
|
|
581
|
+
return '';
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
//# sourceMappingURL=project-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-env.js","sourceRoot":"","sources":["../../src/utils/project-env.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/shell.d.ts
CHANGED
|
@@ -59,6 +59,13 @@ export interface RunShellOptions {
|
|
|
59
59
|
emitEvents?: boolean;
|
|
60
60
|
/** Source label for emitted events (default: 'shell'). */
|
|
61
61
|
source?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Environment overrides merged OVER the inherited process environment
|
|
64
|
+
* (execa's default `extendEnv`). Used to apply a project's pinned virtualenv
|
|
65
|
+
* (PATH/VIRTUAL_ENV) to every subprocess the pipeline runner spawns, so a
|
|
66
|
+
* bare `python`/`pip` resolves to the project env. See project-env.ts.
|
|
67
|
+
*/
|
|
68
|
+
env?: Record<string, string | undefined>;
|
|
62
69
|
}
|
|
63
70
|
/** Result of a `runShell` / `runShellSync` call. */
|
|
64
71
|
export interface RunShellResult {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAQH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAID,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,sEAAsE;IACtE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAQH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAID,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,sEAAsE;IACtE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C;AAED,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,QAAQ,EAAE,OAAO,CAAC;IAClB,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAYD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CA0EtG;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,cAAc,CAuD3F"}
|
package/dist/utils/shell.js
CHANGED
|
@@ -83,6 +83,7 @@ export async function runShell(command, options = {}) {
|
|
|
83
83
|
reject: false,
|
|
84
84
|
signal: options.signal,
|
|
85
85
|
windowsHide: true,
|
|
86
|
+
...(options.env ? { env: options.env } : {}),
|
|
86
87
|
});
|
|
87
88
|
if (options.onChunk && subprocess.all) {
|
|
88
89
|
subprocess.all.on('data', (chunk) => {
|
|
@@ -149,6 +150,7 @@ export function runShellSync(command, options = {}) {
|
|
|
149
150
|
all: true,
|
|
150
151
|
reject: false,
|
|
151
152
|
windowsHide: true,
|
|
153
|
+
...(options.env ? { env: options.env } : {}),
|
|
152
154
|
});
|
|
153
155
|
stdout = result.stdout ?? '';
|
|
154
156
|
stderr = result.stderr ?? '';
|