(runtime: string | undefined)
| 1325 | * - undefined -> Worktree runtime (default) |
| 1326 | */ |
| 1327 | export function parseRuntimeString(runtime: string | undefined): RuntimeConfig | undefined { |
| 1328 | // Use shared parser from common/types/runtime |
| 1329 | const parsed = parseRuntimeModeAndHost(runtime); |
| 1330 | |
| 1331 | // null means invalid input (e.g., "ssh" without host, "docker" without image) |
| 1332 | if (parsed === null) { |
| 1333 | // Determine which error to throw based on input |
| 1334 | const trimmed = runtime?.trim().toLowerCase() ?? ""; |
| 1335 | if (trimmed === RUNTIME_MODE.SSH || trimmed.startsWith("ssh ")) { |
| 1336 | throw new Error("SSH runtime requires host (e.g., 'ssh hostname' or 'ssh user@host')"); |
| 1337 | } |
| 1338 | if (trimmed === RUNTIME_MODE.DOCKER || trimmed.startsWith("docker ")) { |
| 1339 | throw new Error("Docker runtime requires image (e.g., 'docker ubuntu:22.04')"); |
| 1340 | } |
| 1341 | if (trimmed === RUNTIME_MODE.DEVCONTAINER || trimmed.startsWith("devcontainer")) { |
| 1342 | throw new Error( |
| 1343 | "Dev container runtime requires a config path (e.g., 'devcontainer .devcontainer/devcontainer.json')" |
| 1344 | ); |
| 1345 | } |
| 1346 | throw new Error( |
| 1347 | `Unknown runtime type: '${runtime ?? ""}'. Use 'ssh <host>', 'docker <image>', 'devcontainer <config>', 'worktree', or 'local'` |
| 1348 | ); |
| 1349 | } |
| 1350 | |
| 1351 | // Convert ParsedRuntime to RuntimeConfig |
| 1352 | switch (parsed.mode) { |
| 1353 | case RUNTIME_MODE.WORKTREE: |
| 1354 | return undefined; // Let backend use default worktree config |
| 1355 | |
| 1356 | case RUNTIME_MODE.LOCAL: |
| 1357 | return { type: RUNTIME_MODE.LOCAL }; |
| 1358 | |
| 1359 | case RUNTIME_MODE.SSH: |
| 1360 | return { |
| 1361 | type: RUNTIME_MODE.SSH, |
| 1362 | host: parsed.host, |
| 1363 | srcBaseDir: "~/mux", // Default remote base directory (tilde resolved by backend) |
| 1364 | }; |
| 1365 | |
| 1366 | case RUNTIME_MODE.DEVCONTAINER: { |
| 1367 | const configPath = parsed.configPath.trim(); |
| 1368 | if (!configPath) { |
| 1369 | throw new Error( |
| 1370 | "Dev container runtime requires a config path (e.g., 'devcontainer .devcontainer/devcontainer.json')" |
| 1371 | ); |
| 1372 | } |
| 1373 | return { |
| 1374 | type: RUNTIME_MODE.DEVCONTAINER, |
| 1375 | configPath, |
| 1376 | }; |
| 1377 | } |
| 1378 | case RUNTIME_MODE.DOCKER: |
| 1379 | return { |
| 1380 | type: RUNTIME_MODE.DOCKER, |
| 1381 | image: parsed.image, |
| 1382 | }; |
| 1383 | } |
| 1384 | } |
no test coverage detected