You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Extend existing canvas_extensions installation rather than introducing a second package manager or Docker requirement. Preserve schema-1/browser-only Apps. Add a versioned optional backend declaration, capability discovery, typed HTTP lifecycle API and TypeScript client coverage. Execute only a trusted installed package's declared argv with a contained cwd, never client-supplied shell/URL commands. One service per installed app per owning Agent Server initially; no host-global service shared across isolated conversation containers.
Acceptance criteria:
Installation/enabling/mounting never implicitly executes backend code. Explicit preparation/start consent is tied to resolved revision; updates invalidate backend approval.
Status/probe, prepare, start, stop and bounded logs are idempotent or return clear states (missing/stopped/starting/ready/unhealthy/unsupported).
Immutable pinned artifacts with checksum and safe extraction; mutable data/private state outside installed bundle. No ambient credential inheritance; explicit environment allowlist.
Single-flight lifecycle, health timeout, continuously drained bounded logs, owned process-group cleanup on stop/server exit, and failed-start cleanup tested with real subprocesses.
Disable/removal stops owned processes but preserves user data; data deletion is separate. Updating a running backend requires stop/approval, not a silent swap.
Local Linux amd64/arm64 first; unsupported platforms reported explicitly. No Kubernetes/Cloud orchestration or general install hooks.
Related existing work: OpenHands/OpenHands#16289. This is runtime management, not a replacement for the current App installer.
Dependencies and sequencing
Implementation/merge prerequisites (cross-repository links are authoritative):
None; root implementation issue.
Readiness means design/scope accepted; implementation must wait for the triage automation to apply ready-for-dev. Dependent PRs may stack on tested prerequisite branches; they must not merge before prerequisite PRs. No issue should be closed just to bypass sequencing. One issue per PR.
This issue was created by an AI agent (OpenHands) on behalf of Graham Neubig.
OpenHands AI triage
The following comments and acceptance criteria were added by the OpenHands AI agent.
Triage
Scope: extend the existing canvas-extensions ("Apps") installation framework in openhands-agent-server (manifest, canvas_extensions/installed.py, canvas_extensions_router.py) with an optional, versioned per-app backend declaration and an owned-process lifecycle, then propagate the HTTP contract through OpenAPI and clients/typescript. The agent server already owns app install/enable/serve, and canvas-extension.json + resolve_entrypoint are the authoritative manifest/containment mechanism, so the backend declaration belongs there rather than in a new package manager. OpenHands/OpenHands still owns the Canvas UI; this issue is agent-server runtime management only. One owned service per installed app per agent-server instance.
Non-goals: no second package manager, no Docker requirement, no host-global service shared across isolated conversation containers, no Kubernetes/Cloud orchestration, no general install hooks, and never executing client-supplied shell or URL commands.
Assumptions (resolved from the repo, not arbitrary): the declaration is an additive optional block that leaves schema-1/browser-only apps valid; the backend command is an argv list resolved from the installed package, never a shell string; env values flow through openhands.sdk.utils.pydantic_secrets; and the API mirrors the existing plugins/skills router conventions and the existing OpenAPI → TypeScript client generation flow.
Desired Behavior
An installed app may optionally declare a versioned backend. When present, the owning agent server can report status, prepare, start, stop, and return bounded logs for a single owned process per app, per agent-server instance. Installing, enabling, or mounting an app never starts that process; starting requires explicit consent bound to the resolved revision, and a new revision invalidates prior approval. Browser-only schema-1 apps continue to install, enable, and serve unchanged.
Acceptance Criteria
A browser-only, schema-1 app (no backend block) installs, enables, disables, uninstalls, and serves its bundle exactly as before, with no backend lifecycle call required; existing canvas-extensions tests still pass.
A manifest with no backend block and one with a valid backend block both validate; an unsupported or malformed backend declaration is rejected with a clear error and no partial install, rather than being silently accepted.
Installing, enabling, or mounting an app never spawns a backend process; a process is created only after an explicit prepare/start request, observable via the lifecycle state and the process list.
Start consent is bound to the resolved revision (git SHA): after the installed app is updated to a different resolved revision, the earlier approval no longer authorizes starting the new revision.
status/probe, prepare, start, stop, and bounded logs are exposed as typed HTTP operations in the OpenAPI spec and mirrored in clients/typescript.
status/probe reports exactly one of missing / stopped / starting / ready / unhealthy / unsupported; repeated status and prepare calls are idempotent, and prepare/start on an already-ready app succeed without launching a second process.
Start executes only the installed package's declared argv, with no shell interpretation and no client-supplied command or URL, and with cwd contained inside the installed app directory.
Health checking is bounded: a backend that never becomes healthy within the timeout is reported unhealthy (or a failed start) instead of hanging, and its process is cleaned up so no orphan remains.
Concurrent prepare/start/stop calls for the same app are single-flighted: at most one process is created and every caller observes a consistent state.
Backend stdout/stderr are drained continuously so sustained output cannot block the process on a full pipe, and returned logs are size-bounded.
stop terminates the app's whole owned process group, and agent-server exit terminates owned backend processes; neither path leaves orphaned children.
Failed-start cleanup is exercised with a real subprocess, covering at least a start that exits nonzero or never becomes ready.
Disabling or uninstalling an app stops its owned process while preserving mutable user data; deleting that data requires a separate, explicit action.
Updating a running backend does not silently swap the process: it must be stopped and the new revision approved before it is started.
The backend receives only an explicit environment allowlist; ambient agent-server credentials/secrets are not inherited by default, and declared secret values use openhands.sdk.utils.pydantic_secrets (no parallel redaction path).
Pinned artifacts are immutable and checksum-verified with safe extraction; mutable data and private state are written outside the installed bundle directory.
On Linux amd64 and arm64 the lifecycle works end-to-end with a real subprocess; on an unsupported platform a request explicitly reports unsupported rather than failing obscurely.
Documentation covers the manifest backend declaration, the lifecycle API, and the trust/consent model for starting a backend.
Unit and integration tests cover the lifecycle plus its failure and edge cases (unsupported platform, unhealthy start, concurrent calls, disable/stop with retained data), using real subprocesses rather than mocks.
Extend existing canvas_extensions installation rather than introducing a second package manager or Docker requirement. Preserve schema-1/browser-only Apps. Add a versioned optional backend declaration, capability discovery, typed HTTP lifecycle API and TypeScript client coverage. Execute only a trusted installed package's declared argv with a contained cwd, never client-supplied shell/URL commands. One service per installed app per owning Agent Server initially; no host-global service shared across isolated conversation containers.
Acceptance criteria:
Related existing work: OpenHands/OpenHands#16289. This is runtime management, not a replacement for the current App installer.
Dependencies and sequencing
Implementation/merge prerequisites (cross-repository links are authoritative):
Readiness means design/scope accepted; implementation must wait for the triage automation to apply ready-for-dev. Dependent PRs may stack on tested prerequisite branches; they must not merge before prerequisite PRs. No issue should be closed just to bypass sequencing. One issue per PR.
This issue was created by an AI agent (OpenHands) on behalf of Graham Neubig.
OpenHands AI triage
The following comments and acceptance criteria were added by the OpenHands AI agent.
Triage
Scope: extend the existing canvas-extensions ("Apps") installation framework in
openhands-agent-server(manifest,canvas_extensions/installed.py,canvas_extensions_router.py) with an optional, versioned per-app backend declaration and an owned-process lifecycle, then propagate the HTTP contract through OpenAPI andclients/typescript. The agent server already owns app install/enable/serve, andcanvas-extension.json+resolve_entrypointare the authoritative manifest/containment mechanism, so the backend declaration belongs there rather than in a new package manager.OpenHands/OpenHandsstill owns the Canvas UI; this issue is agent-server runtime management only. One owned service per installed app per agent-server instance.Non-goals: no second package manager, no Docker requirement, no host-global service shared across isolated conversation containers, no Kubernetes/Cloud orchestration, no general install hooks, and never executing client-supplied shell or URL commands.
Assumptions (resolved from the repo, not arbitrary): the declaration is an additive optional block that leaves schema-1/browser-only apps valid; the backend command is an argv list resolved from the installed package, never a shell string; env values flow through
openhands.sdk.utils.pydantic_secrets; and the API mirrors the existing plugins/skills router conventions and the existing OpenAPI → TypeScript client generation flow.Desired Behavior
An installed app may optionally declare a versioned backend. When present, the owning agent server can report status, prepare, start, stop, and return bounded logs for a single owned process per app, per agent-server instance. Installing, enabling, or mounting an app never starts that process; starting requires explicit consent bound to the resolved revision, and a new revision invalidates prior approval. Browser-only schema-1 apps continue to install, enable, and serve unchanged.
Acceptance Criteria
clients/typescript.missing/stopped/starting/ready/unhealthy/unsupported; repeated status and prepare calls are idempotent, and prepare/start on an already-ready app succeed without launching a second process.unhealthy(or a failed start) instead of hanging, and its process is cleaned up so no orphan remains.openhands.sdk.utils.pydantic_secrets(no parallel redaction path).unsupportedrather than failing obscurely.