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