Skip to content

feat(agent-server): add standalone prompt enhancement API - #5446

Open
KevinAndrewDong wants to merge 13 commits into
OpenHands:mainfrom
KevinAndrewDong:codex/prompt-enhancement-5217
Open

KevinAndrewDong wants to merge 13 commits into
OpenHands:mainfrom
KevinAndrewDong:codex/prompt-enhancement-5217

Conversation

@KevinAndrewDong

@KevinAndrewDong KevinAndrewDong commented Oct 1, 2026 •

Copy link
Copy Markdown

HUMAN:
I shaped the scope and provided review feedback.


AGENT:

AI assistance

Tool(s) used: Codex
How you used it: Assisted with the API/SDK implementation, regression tests, and independent AI review.

Why

This adds the server-side prompt enhancement operation and typed TypeScript access requested in #5217, so clients can improve a draft before starting a conversation while credentials remain server-side.

Summary

  • Add authenticated availability and enhancement routes that resolve saved profiles server-side, make one bounded no-tools LLM call, validate output, and return stable errors.
  • Add typed TypeScript methods with AbortSignal support and endpoint-generated OpenAPI types while keeping the full generated schema pinned to the published Agent Server image.
  • Regenerate the prompt-enhancement contract from the current branch OpenAPI and freshness-check it in TypeScript CI.
  • Guard payload-capturing tracing. Disable completion logging, retries, and prompt-cache fallback only on the one-off LLM copy; retain the saved profile and normal SDK behavior.
  • Cover error mappings, timeout, cancellation, privacy, multilingual preservation, provider transport call counts, and authenticated live HTTP integration.

Issue Number

Fixes #5217

How to Test

  • uv run pytest -q tests/agent_server/test_prompt_enhancement_router.py tests/agent_server/test_server_details_router.py tests/agent_server/test_openapi_contract.py tests/agent_server/test_openapi_discriminator.py — 69 passed on Python 3.12, 3.13, and 3.14. The new transport-level regression covers chat and Responses success/cache-error paths; each invokes the provider stub once.
  • uv run pytest -q tests/cross/test_remote_conversation_live_server.py::test_prompt_enhancement_over_authenticated_live_http — passed against real Uvicorn on the final Python 3.13 snapshot, including authentication, capabilities, saved profiles, and unchanged conversation/profile state.
  • cd clients/typescript && npm run test:coverage — 360 passed on Node 22; the same 360 tests passed on Node 24. The compiled client also passed availability and enhancement against the real Python HTTP server on both versions.
  • In clients/typescript: npm run test:agent-server-api-tooling, npm run check:prompt-enhancement-api, npm run check:agent-server-api, npm run build, npm run lint, and npm run format:check passed. Lint reported 7 existing warnings.
  • Repository pre-commit checks passed for the complete PR's changed files, including pyright and import/tool registration checks.
  • Provider calls were stubbed; no live model credentials were used. On headless macOS, the test launcher disabled unrelated browser-use display detection; the live HTTP test disables unrelated tool discovery/preloading.
  • These are local results. Upstream GitHub Actions and maintainer review remain separate verification steps.

Video/Screenshots

Not applicable; this adds an API and SDK method without a UI change.

Type

  • Bug fix
  • Feature
  • Refactor
  • Breaking change
  • Docs / chore

Notes

Prompt enhancement is unavailable while LLM tracing or payload logging is enabled, including context-only OpenTelemetry instrumentation: provider exception spans can contain private draft text. Profile-store lock waits run off the event loop so the endpoint deadline remains effective. A caller-owned AbortSignal also cancels the initial capability probe.

KevinAndrewDong and others added 3 commits October 1, 2026 23:07
Co-authored-by: openhands <openhands@all-hands.dev>
Use endpoint-generated OpenAPI types, preserve payload privacy with context-only tracing, and cover provider errors, cancellation, and multilingual preservation.

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
@KevinAndrewDong
KevinAndrewDong marked this pull request as ready for review October 2, 2026 05:43
KevinAndrewDong and others added 2 commits October 3, 2026 09:43
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
@neubig
neubig requested a review from all-hands-bot October 3, 2026 21:35
@all-hands-bot

all-hands-bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator

⏳ Review waiting on checks

The current head b5c79948ed83 still has checks that have not finished, so no review conversation was started:

  • Agent Server
  • Check Docstrings
  • Deprecation deadlines
  • Persisted settings compatibility checks
  • Pre-commit checks
  • REST API breakage checks
  • Review Thread Gate
  • Run tests
  • TypeScript client CI
  • TypeScript client endpoint audit
  • TypeScript client integration tests
  • Version bump guard

No action is needed. The scheduled scan retries once every check on the head reports a conclusion.

This is an automated check - no AI was used to generate this comment.

@neubig
neubig requested review from all-hands-bot and removed request for all-hands-bot October 3, 2026 23:37

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This review was posted by an AI agent (OpenHands).

Review: PR #5446 — feat(agent-server): add standalone prompt enhancement API

Head reviewed: 2a35a405fe8f5aa39b3ac067540b84a9bb2943c1 (matches the requested head; no prior reviews or comments from this account).

Scope

In scope. This is the Agent Server REST operation plus its clients/typescript/ mirror, matching the repository ownership rule (SDK/Agent Server -> OpenAPI -> TypeScript client). The Canvas UI portion stays in OpenHands/OpenHands per issue #5217, which carries ready-for-dev and priority:low.

Verified on the current head

  • No side effects / server-side credentials. _load_profile resolves the saved profile via get_llm_profile_store().load(..., cipher=config.cipher) and enhance_prompt makes one no-tools call (tools=[], max_tokens=MAX_OUTPUT_TOKENS, store=False for the Responses API). _quiet_llm forces log_completions=False / num_retries=0 on a copy, so the stored profile is untouched; tests assert conversation count, active profile, and active agent profile are unchanged and the profile's own log_completions stays True.
  • Privacy fail-closed. _prompt_payload_capture_enabled() blocks enhancement when DEBUG_LLM is set or should_enable_observability() is true, and the 422 validation handler now drops raw input for /api/prompt-enhancement/ paths. Tests cover provider-error text, exception-tracing spans, malformed/duplicate JSON, and oversized/parser payloads not echoing drafts or credentials.
  • Limits, timeout, cancellation. Input/output length limits are enforced in both Pydantic and the route; asyncio.timeout wraps profile load and the provider call; the profile-lock wait runs through asyncio.to_thread so the endpoint deadline still fires (test test_profile_lock_wait_respects_endpoint_timeout). asyncio.CancelledError propagates (it is a BaseException, not caught by the broad except Exception).
  • Client + generated contract. PromptEnhancementClient gates on the prompt_enhancement_v1 capability, maps typed error bodies, and threads a caller AbortSignal through the probe and the enhance call. The checked-in prompt-enhancement-schema.ts matches regeneration from the current branch's OpenAPI (verified locally with npm run check:prompt-enhancement-api).

Verification run

  • uv run pytest -q tests/agent_server/test_prompt_enhancement_router.py tests/agent_server/test_server_details_router.py tests/agent_server/test_openapi_contract.py tests/agent_server/test_openapi_discriminator.py -> 55 passed.
  • npm run test:agent-server-api-tooling, npm run check:prompt-enhancement-api, and the prompt-enhancement client vitest file (6 tests) -> pass.

Non-blocking observation

On the current head, GitHub Actions has only completed the PR-hygiene checks (Validate PR description, check-pr-artifacts -> success); the code checks (Run tests, TypeScript client CI, REST API breakage checks, etc.) are action_required/awaiting approval and have not exercised this commit. The author's local results and my own focused runs are green, but a maintainer should confirm the full CI set runs on this head before merge.

No material correctness, security, compatibility, or acceptance-criterion defect found in the current head.

✅ APPROVED

KevinAndrewDong and others added 2 commits October 4, 2026 08:50
Co-authored-by: openhands <openhands@all-hands.dev>
Use the matched route to omit private draft inputs from validation errors, including runtime-prefixed requests. Cover prefixed field validation and malformed or resource-heavy JSON with the existing tests.

Co-authored-by: openhands <openhands@all-hands.dev>
KevinAndrewDong and others added 3 commits October 8, 2026 02:20
Disable prompt-cache fallback on the endpoint-local LLM copy and cover chat
and Responses transport counts. Verify authenticated enhancement over a
real Agent Server HTTP connection without mutating saved state.

Co-authored-by: openhands <openhands@all-hands.dev>
Preserve live-server fixture preload and deferred initialization controls.

Co-authored-by: openhands <openhands@all-hands.dev>
Merge current main, retain both server capabilities, enforce the SDK output budget, and reject provider options that bypass enhancement boundaries. Add transport regressions and real-server verification recipes.

Co-authored-by: openhands <openhands@all-hands.dev>
@neubig
neubig requested review from all-hands-bot and removed request for all-hands-bot October 16, 2026 14:19

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This review was posted by an AI agent (OpenHands).

Review: PR #5446 — feat(agent-server): add standalone prompt enhancement API

Head reviewed: b5c79948ed830cdb0598a57925ee01f1307e0ca7. No prior review exists on this head (the earlier approval was on the previous head 2a35a405fe8f), so this is a fresh pass.

Scope

In scope. The change is the Agent Server REST operation plus its clients/typescript/ mirror, matching the repository ownership rule (SDK/Agent Server → OpenAPI → typed client). The Canvas UI portion stays in OpenHands/OpenHands per issue #5217, which still carries ready-for-dev and priority:low.

What the current head does

  • Server-side credentials, no side effects. _load_profile resolves the saved profile through get_llm_profile_store().load(..., cipher=config.cipher); enhance_prompt then makes one no-tools call (tools=[], store=False on the Responses path). _quiet_llm copies the LLM and forces log_completions=False, num_retries=0, caching_prompt=False, and a bounded max_output_tokens, leaving the stored profile and normal SDK behavior untouched — the live-HTTP and unit tests assert conversation count, profile list, the saved profile, and its log_completions are unchanged.
  • Bounded generation. The token budget is now set on the LLM copy (min(effective_max_output_tokens or MAX_OUTPUT_TOKENS, MAX_OUTPUT_TOKENS)) rather than passed as a per-call kwarg, and the code rejects subscription profiles and any non-empty litellm_extra_body (which providers merge after normal parameters and could restore tools/storage or raise the budget) with a stable unsupported_configuration error. Tests cover chat/Responses and Azure budget-key mapping across profile budgets.
  • Privacy fail-closed. Enhancement is refused while DEBUG_LLM is set or should_enable_observability() is true, and the 422 handler omits raw input for /api/prompt-enhancement/ routes using the matched route path (root_path-aware). Tests cover provider-error text, exception-tracing spans, malformed/duplicate/oversized JSON, and a live authenticated server.
  • Limits, timeout, cancellation. Input/output length limits are enforced in the route; asyncio.timeout wraps profile load and the provider call; the profile-lock wait runs via asyncio.to_thread so the deadline still fires; CancelledError propagates. The generated TypeScript contract matches the current-branch OpenAPI.

Verification performed

  • uv run pytest -q tests/agent_server/test_prompt_enhancement_router.py tests/agent_server/test_server_details_router.py tests/agent_server/test_openapi_contract.py tests/agent_server/test_openapi_discriminator.py → 89 passed.
  • npm run test:agent-server-api-tooling, npm run check:prompt-enhancement-api, and the prompt-enhancement client vitest file (6 tests) → pass.

Note for the maintainer: in my sandbox LMNR_PROJECT_API_KEY was set, which globally enables observability and (correctly) makes these routes return unsupported_configuration. With that ambient variable unset — the normal case for the author's local runs and for environments without tracing — all 89 tests pass. This is a fail-closed behavior, not a defect.

Non-blocking observation

On this head, GitHub Actions has only completed the PR-hygiene checks (Validate PR description, check-pr-artifacts → success); the code checks (Run tests, TypeScript client CI, REST API breakage checks, etc.) have not run and are awaiting repository approval. The author's local results and my focused runs are green, but a maintainer should confirm the full CI set runs on this head before merge.

No material correctness, security, compatibility, or acceptance-criterion defect found in the current head.

✅ APPROVED

KevinAndrewDong and others added 2 commits October 22, 2026 16:21
Resolve the feature-map count as 941, preserving main's 936 sub-features and the five prompt-enhancement additions.

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
@github-actions

Copy link
Copy Markdown
Contributor

📁 PR Artifacts Notice

This PR contains a .pr/ directory with temporary PR-specific documents. The directory will be automatically removed after this PR merges to main through a cleanup PR.

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This review was posted by an AI agent (OpenHands).

Reviewed head 592fd232468675449c7c221078f35ce690e47529 (re-fetched current state: PR open, non-draft, head unchanged, no existing review on this head, no unresolved threads).

Scope: Belongs in this repository. It adds an Agent Server REST route plus /server_info capability and mirrors it in clients/typescript, following the repo's Agent Server → OpenAPI → TypeScript client flow to deliver #5217 (currently labeled ready-for-dev). The change is additive: existing /api/profiles, /api/agent-profiles, and /server_info response shapes keep their behavior, and _sanitize_validation_errors preserves its previous output for every non-prompt-enhancement route.

Verification on this head:

  • uv run pytest tests/agent_server/test_prompt_enhancement_router.py tests/agent_server/test_server_details_router.py tests/agent_server/test_openapi_contract.py tests/agent_server/test_openapi_discriminator.py — 91 passed in the workspace.
  • tests/cross/test_remote_conversation_live_server.py::test_prompt_enhancement_over_authenticated_live_http — passed (auth enforced, capability advertised, saved profile unchanged, no conversation side effects).
  • Traced the design against base behavior: system-before-user message invariant holds; the chat path passes no tools (tools resolves to None for an empty list) and the Responses path passes store=False with no tools; profile credentials flow through the existing profile store and cipher with log_completions=False, num_retries=0, prompt caching off, and an 8,192-token output cap on the one-off copy only; payload-capturing tracing (DEBUG_LLM and observability, including context-only OTel) fails closed with a typed error; the 45s asyncio.timeout remains effective because profile-store lock waits run in asyncio.to_thread; error codes cover every class required by #5217, and the transport-level tests assert exactly one provider call per request.
  • No new third-party npm or PyPI versions were introduced; the new workflow step pins astral-sh/setup-uv to a full SHA.

CI note: agent-server-stress-tests is the only failing check on this head, failing in test_concurrent_conversations_isolated_and_fast, a wall-clock parallelism budget assertion. The PR's diff touches none of the measured path (no conversation-run, lock, or stress-suite changes), and the identical assertion failure reproduces on pristine origin/main in the same environment (4/4 runs on each head, ~0.8s concurrent wall vs a ~0.63s budget), so this is an unrelated, environment-sensitive flaky budget rather than a regression from this PR. Recent main runs pass the same check, so the budget appears marginal under runner variance.

No material correctness, security, compatibility, or acceptance findings on this diff.

✅ APPROVED

Co-authored-by: openhands <openhands@all-hands.dev>
@KevinAndrewDong
KevinAndrewDong force-pushed the codex/prompt-enhancement-5217 branch from ffcd00f to 592fd23 Compare October 27, 2026 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add a standalone prompt-enhancement API and TypeScript client support

4 participants