* Update extensions to 0.9
* test: account for jira-issue-to-pr automation in extensions 0.9.0
@openhands/extensions 0.9.0 adds the jira-issue-to-pr recommended
automation (popularityRank 85, beta). Update the recommended-automations
tests to include it in the popularity-ordered list and bump the Beta
section count from 4 to 5.
---------
Co-authored-by: openhands <openhands@all-hands.dev>
* chore: bump typescript-client 1.32.1 + agent-server/openhands-sdk 1.33.0
- @openhands/typescript-client 1.32.0 -> 1.32.1 (package.json + lockfile)
- agent-server SDK libs (openhands-sdk/tools/workspace/agent-server) 1.32.0 -> 1.33.0 via versions.agentServer in config/defaults.json
- sweep doc/test/comment references to 1.33.0 (AGENTS.md, dev-safe.test.ts, check-sdk-version-sync.mjs, dev-safe.mjs, mock-llm-e2e.yml)
- keep the acp <0.11 transitive pin: openhands-sdk 1.33.0 still requires agent-client-protocol>=0.10.1 with no upper bound
Note: check-sdk-version-sync fails until an openhands-automation release pins openhands-sdk 1.33.0. The latest automation (1.1.3) still pins 1.32.0, so versions.automation is left at 1.1.3.
* chore: bump openhands-automation 1.1.3 -> 1.1.4 (pins SDK 1.33.0)
openhands-automation 1.1.4 is now published on PyPI and pins
openhands-sdk/openhands-workspace to 1.33.0, matching versions.agentServer.
This satisfies the check-sdk-version-sync check, which failed while
automation stayed at 1.1.3 (pinned SDK 1.32.0). Consolidates the
SDK+automation bump from #1622 into this PR alongside the ts-client bump.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Debug Agent <157206163+simonrosenberg@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Squash merge PR #1583.
This merge commit was created by an AI agent (OpenHands) on behalf of Graham Neubig.
Co-authored-by: openhands <openhands@all-hands.dev>
* Use libraries for local proxy and static serving
* Fix CI for proxy library refactor
* Fix static server CI failures
Co-authored-by: openhands <openhands@all-hands.dev>
---------
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: openhands <openhands@all-hands.dev>
* fix(examples): inherit acp-docker image from config/defaults.json
examples/acp-docker/docker-compose.yml hardcoded the agent-server image at
`1.25.0-python`. Canvas enforces `compatibility.minimumAgentServer` (1.28.0)
from the repo's single source of truth, so the example default fell below the
floor and rendered "Disconnected — requires 1.28.0 or newer" — a reviewer
following the quickstart as written never reached the feature.
examples/acp-docker was the lone in-repo file hardcoding a version instead of
inheriting from config/defaults.json (14 other files read it; check-sdk-version
-sync only validates the released PyPI package, not in-repo files).
- scripts/gen-acp-docker-env.mjs: read defaults.json, pin AGENT_SERVER_IMAGE to
`${images.agentServer}:${versions.agentServer}-python` in examples/acp-docker
/.env (idempotent upsert; mirrors scripts/docker-build.mjs).
- package.json: `npm run example:acp-docker:env`.
- docker-compose.yml: no-config fallback `1.25.0-python` -> `latest-python`,
always >= the compatibility floor, so zero-config `docker compose up` never
shows "Disconnected"; the generated .env overrides with the pinned SoT
version for the reproducible path.
- .env.example / README.md: document both paths; correct the version narrative
(floor is the defaults.json compatibility pin; #3510 is the deeper functional
floor at/below it).
- __tests__/scripts/acp-docker-env-sync.test.ts: assert the generator's tag
matches defaults.json, the pin satisfies the floor, and the compose fallback
stays `latest-python`. Mirrors docs-version-sync.test.ts — the guard that
makes "can't silently drift" true.
* test(examples): harden acp-docker env-sync per review
Addresses the cli-review-panel findings worth acting on (the rest were
cosmetic or matched the no-validation idiom of scripts/docker-build.mjs):
- gte() in the test guarded with parseSemver — a non-numeric pin (sha /
pre-release) now fails the floor check loudly instead of silently
comparing NaN. The floor check is a CI gate; its one piece of logic
shouldn't mis-compare in silence.
- compose-fallback assertion derives the registry from config.images
.agentServer instead of hardcoding ghcr.io/openhands/... — a registry
change no longer false-fails a test that only cares about the latest-python
tag.
- upsertEnvLine now has unit tests (append / replace-in-place+preserve /
idempotent / commented-template-line / keyless-line guard), making the
"idempotent upsert" claim defensible. It was the one untested piece of real
logic.
- upsertEnvLine guards a keyless line (no "=") with a clear throw, instead of
an empty key matching every line and rewriting the whole file.
* fix(examples): guard acp-docker env-sync entrypoint against undefined argv[1]
The CLI entrypoint guard called pathToFileURL(process.argv[1]) unconditionally.
process.argv[1] is undefined in some ESM contexts (e.g. importing the module for
its exports via `node --input-type=module -e "import(...)"`), so the guard threw
ERR_INVALID_ARG_TYPE at import, before any exported helper was reachable.
Short-circuit on process.argv[1] before pathToFileURL so importing the module is
side-effect-free while the CLI path is unchanged. Add a regression test that
reproduces the bare-import context and asserts a clean exit.
Addresses the review finding on #1434.
* docs(acp-docker): trim verbose comments per review
Address all-hands-bot's review suggestions on #1434:
- test header describes the current invariant, not the prior-state history
(that narration belonged in the PR description)
- docker-compose.yml: condense the image-pin comment to the how-to-override;
the compatibility-floor / #3510 rationale already lives in README §1 + the test
- .env.example: 7-line pin explainer down to 2
Comment-only; env-sync test still 10/10 green, prettier clean.
* Clarify ACP Docker image version guidance
Co-authored-by: openhands <openhands@all-hands.dev>
---------
Co-authored-by: enyst <engel.nyst@gmail.com>
Co-authored-by: openhands <openhands@all-hands.dev>
* chore(deps): bump @openhands/typescript-client to 1.27.0
* test: update ACP provider/model fixtures for typescript-client 1.27.0
1.27.0 refreshed the claude-code/codex ACP registry data: provider command
versions (claude-agent-acp 0.30.0->0.44.0, codex-acp 0.15.0->0.16.0),
claude-code model ids (claude-opus-4-8->opus[1m], claude-sonnet-4-6->sonnet,
claude-haiku-4-5->haiku) plus a new well-labeled "default" option, and the
codex default (gpt-5.5/medium->gpt-5.5).
Canvas sources these lists from the client registry (closes#740), so the
source was already correct -- only the hardcoded test expectations were
stale. Also relaxed the acp-providers placeholder guard to accept the SDK's
intentional "Default (recommended)" entry.
* chore(deps): bump agent-server/openhands-sdk to 1.29.0
Align the spawned agent-server SDK release train (openhands-sdk,
openhands-tools, openhands-workspace, openhands-agent-server) with the
version @openhands/typescript-client 1.27.0 is validated against
(agent-server 1.29.0-python). Bump the coupled openhands-automation pin
to 1.0.0a12, whose SDK deps resolve to 1.29.0, to satisfy the
check-sdk-version-sync gate. minimumAgentServer compat floor unchanged.
Doc/JSDoc/test references updated to keep docs-version-sync green.
* Update typescript-client to v1.25.0 with pinned ACP versions
Upgrades from v1.24.3 to v1.25.0 to get the ACP provider version pins:
- claude-agent-acp@0.30.0
- codex-acp@0.15.0
- gemini-cli@0.38.0
Fixes the 'Method not found' error when starting Codex ACP sessions.
The unpinned npm package was resolving to codex-acp@0.16.0 which
lacks the session/set_model RPC method that the SDK expects.
Closes: agent-canvas#<issue> (codex version incompatibility)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* chore: update package-lock.json typescript-client version to 1.25.0
Synchronize lockfile dependency version with package.json to fix npm ci validation.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* chore: complete lockfile update for typescript-client@1.25.0
Update both dependency version and package definition with correct integrity hash.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* test: update ACP provider command expectations for pinned versions
Update test expectations to match typescript-client@1.25.0 registry which includes
version pins: claude-agent-acp@0.30.0, codex-acp@0.15.0, gemini-cli@0.38.0.
These pins fix the 'Method not found' error on Codex ACP sessions by ensuring
npm resolves to compatible versions.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* fix: update ACP test expectations for typescript-client@1.25.0 pinned versions
- Change empty acp_command to fall back to registry defaults (now with pinned versions)
- Update expected Claude Code default model from opus-4-7 to opus-4-8
* fix: update test expectations for typescript-client@1.25.0 registry changes
- Default Claude Code model updated: claude-opus-4-7 → claude-opus-4-8
- Pinned commands now include version: @claude-agent-acp@0.30.0, @codex-acp@0.15.0
- Credential tests load acp_command:[] so preset detection finds claude-code
- Reconciles test types pinned codex command to match registry
---------
Co-authored-by: Debug Agent <simon@openhands.dev>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
* Add Windows portability guards for workspace flows
* Increase snapshot workflow timeout
* Trigger CI after timeout update
* Fix windows portability PR after main merge
---------
Co-authored-by: neubig <398875+neubig@users.noreply.github.com>
* chore: bump agent-server → 1.28.1, automation → 1.0.0a9, extensions → 0.4.1
Co-authored-by: openhands <openhands@all-hands.dev>
* Test fixes
* fix: inject proxy base_url for litellm_proxy/* when server omits it (agent-server ≥1.28)
Agent-server ≥1.28 may return base_url:null when fetching a litellm_proxy/*
profile config, even when the profile was saved with the All-Hands proxy URL.
This caused the Basic-tab re-save flow in LlmSettingsLocalView.handleSave to
call isOpenHandsProxyModel(model, null) → false, hitting the else-branch that
deletes base_url and stranding the profile (issue #1146).
Fix: add a secondary check — litellm_proxy/* with a missing base_url is treated
the same as litellm_proxy/* with the proxy URL already set, and
OPENHANDS_LLM_PROXY_BASE_URL is injected before the save request is sent.
Also updates the mock-LLM E2E test to accept both storage representations:
- litellm_proxy/* + proxyBaseUrl (pre-1.28, guards issue #1146 regression)
- openhands/* + null (1.28+, server-managed routing)
And adds a unit test exercising the base_url:null path.
Co-authored-by: openhands <openhands@all-hands.dev>
---------
Co-authored-by: openhands <openhands@all-hands.dev>
* chore: bump agent-server → 1.28.1, automation → 1.0.0a9, extensions → 0.4.1
Co-authored-by: openhands <openhands@all-hands.dev>
* chore: update doc examples to reference agent-server 1.28.1
Update version references in AGENTS.md, scripts/dev-safe.mjs, and
scripts/check-sdk-version-sync.mjs from 1.27.0 → 1.28.1 to stay
in sync with the agentServer pin in config/defaults.json.
Fixes: docs-version-sync.test.ts failures
Co-authored-by: openhands <openhands@all-hands.dev>
* fix: inject proxy base_url for litellm_proxy/* when server omits it (agent-server ≥1.28)
Agent-server ≥1.28 may return base_url:null when fetching a litellm_proxy/*
profile config, even when the profile was saved with the All-Hands proxy URL.
This caused the Basic-tab re-save flow in LlmSettingsLocalView.handleSave to
call isOpenHandsProxyModel(model, '') → false, hitting the else-branch that
deletes base_url and stranding the profile (issue #1146).
Fix: add a secondary check for litellm_proxy/* models with a missing base_url
(null/undefined/empty), treating them the same as a stored proxy URL and
injecting OPENHANDS_LLM_PROXY_BASE_URL before the save request is sent.
Also adds a unit test exercising the base_url:null path.
Co-authored-by: openhands <openhands@all-hands.dev>
* test(e2e): accept agent-server 1.28 model rewrite in proxy profile test
Agent-server 1.28 normalises litellm_proxy/* → openhands/* on storage
and manages the proxy URL internally (returning base_url:null). The old
assertions hard-coded the pre-1.28 storage format (litellm_proxy/* +
explicit proxy URL), causing the test to fail on every 1.28 run.
Extract assertProxyProfileConfig() helper that accepts both storage
representations:
- litellm_proxy/* + proxyBaseUrl (pre-1.28, guards issue #1146 regression)
- openhands/* + null (1.28+, server-managed routing)
The issue #1146 guard is preserved: a litellm_proxy/* profile without a
proxy URL is still flagged as a stranded profile.
Co-authored-by: openhands <openhands@all-hands.dev>
---------
Co-authored-by: openhands <openhands@all-hands.dev>
Keep package metadata in sync with config/defaults.json so npm scripts and mock E2E logs report the current agent-canvas RC version.
Co-authored-by: openhands <openhands@all-hands.dev>