(command: string, payload: Record<string, unknown> = {})
| 157 | } |
| 158 | |
| 159 | export async function callPythonHelper<T>(command: string, payload: Record<string, unknown> = {}): Promise<T> { |
| 160 | await ensureBootstrapped() |
| 161 | const { code, stdout, stderr } = await execFileNoThrow( |
| 162 | pythonBinPath(), |
| 163 | [helperPath, command, '--payload', JSON.stringify(payload)], |
| 164 | { useCwd: false, env: getPythonCommandEnv() }, |
| 165 | ) |
| 166 | |
| 167 | if (code !== 0 && !stdout.trim()) { |
| 168 | throw new Error(stderr || `Python helper ${command} failed with code ${code}`) |
| 169 | } |
| 170 | |
| 171 | let parsed: { ok: boolean; result?: T; error?: { message?: string } } |
| 172 | try { |
| 173 | parsed = JSON.parse(stdout) |
| 174 | } catch { |
| 175 | throw new Error(stderr || stdout || `Python helper ${command} returned invalid JSON`) |
| 176 | } |
| 177 | |
| 178 | if (!parsed.ok) { |
| 179 | throw new Error(parsed.error?.message || `Python helper ${command} failed`) |
| 180 | } |
| 181 | |
| 182 | return parsed.result as T |
| 183 | } |
| 184 | |
| 185 | export function getRuntimePaths(): { projectRoot: string; runtimeStateRoot: string; venvRoot: string } { |
| 186 | return { projectRoot, runtimeStateRoot, venvRoot } |
no test coverage detected