(env = process.env)
| 411 | * @returns {{ command: string, args: string[], source: string }} |
| 412 | */ |
| 413 | export function buildAgentServerCommand(env = process.env) { |
| 414 | const localPath = env.OH_AGENT_SERVER_LOCAL_PATH; |
| 415 | const gitRef = env.OH_AGENT_SERVER_GIT_REF; |
| 416 | const version = env.OH_AGENT_SERVER_VERSION; |
| 417 | |
| 418 | const uvxArgs = []; |
| 419 | let source = ""; |
| 420 | |
| 421 | if (localPath) { |
| 422 | if (!path.isAbsolute(localPath)) { |
| 423 | throw new Error( |
| 424 | `OH_AGENT_SERVER_LOCAL_PATH must be an absolute path, got: ${localPath}`, |
| 425 | ); |
| 426 | } |
| 427 | uvxArgs.push( |
| 428 | "--reinstall", |
| 429 | "--from", |
| 430 | path.join(localPath, "openhands-agent-server"), |
| 431 | "--with-editable", |
| 432 | path.join(localPath, "openhands-sdk"), |
| 433 | "--with-editable", |
| 434 | path.join(localPath, "openhands-tools"), |
| 435 | "--with-editable", |
| 436 | path.join(localPath, "openhands-workspace"), |
| 437 | "agent-server", |
| 438 | ); |
| 439 | source = `local (${localPath})`; |
| 440 | } else if (gitRef) { |
| 441 | // Use git ref with subdirectory syntax for uv workspace monorepo. |
| 442 | // The software-agent-sdk repo has packages in subdirectories: |
| 443 | // openhands-agent-server/, openhands-sdk/, openhands-tools/, openhands-workspace/ |
| 444 | // All four must come from the same ref so inter-package APIs stay in sync. |
| 445 | // |
| 446 | // --reinstall is required because the git branch may carry the same version |
| 447 | // string as the current PyPI release (e.g. both "1.26.0"). Without it, uv |
| 448 | // silently reuses the cached PyPI wheels and the git ref is never actually |
| 449 | // used, even though it was explicitly requested. |
| 450 | const baseGitUrl = `git+${AGENT_SERVER_GIT_REPO}@${gitRef}`; |
| 451 | uvxArgs.push( |
| 452 | "--reinstall", |
| 453 | "--from", |
| 454 | `${baseGitUrl}#subdirectory=openhands-agent-server`, |
| 455 | "--with", |
| 456 | `${baseGitUrl}#subdirectory=openhands-sdk`, |
| 457 | "--with", |
| 458 | `${baseGitUrl}#subdirectory=openhands-tools`, |
| 459 | "--with", |
| 460 | `${baseGitUrl}#subdirectory=openhands-workspace`, |
| 461 | "agent-server", |
| 462 | ); |
| 463 | source = `git (${gitRef})`; |
| 464 | } else if (version) { |
| 465 | // Use specific PyPI version: uvx --from openhands-agent-server==version agent-server |
| 466 | // The package name differs from the executable name, so we need --from syntax |
| 467 | // Pin all SDK packages to the same version for consistency |
| 468 | uvxArgs.push( |
| 469 | "--from", |
| 470 | `${DEFAULT_AGENT_SERVER_PACKAGE}==${version}`, |
no outgoing calls
no test coverage detected