← Engel’s Code Design Notebook

OpenHands / verification field notes

The repair queue.

What each fix changes.
A short summary. A link to the code.

126
fix PRs · 108 open · 18 merged · 0 closed

The verify-agent-server feature map let agents use the real API and record unexpected behavior. This page tracks the fleet’s fixes for those findings, including merged and closed PRs.

Status checked at the time above. Approved does not mean merged. Approval reflects GitHub’s review decision and may come from a bot. Merged changes may not be released yet. PRs with a “Decision needed” section appear first. PR links open in a new tab.

Merged 18Approved 98Open (not approved) 10Changes requested 0Draft 0Closed 0

Decision needed 57

These PR descriptions contain a “Decision needed” section. Open PRs come first: 47 open, 10 merged or closed. The label records the section’s presence; it does not mean a decision is still unresolved after merge.

#5972

◆ Decision needed · PR description

The server sends full webhook batches in the background. A slow receiver no longer keeps a finished run busy.

Original PR title

fix(agent-server): post full webhook batches off the event's publish

#5958

◆ Decision needed · PR description

The server rejects a new conversation if it cannot import a required custom tool module. It no longer accepts the conversation and fails on its first message.

Original PR title

fix(agent-server): reject a create whose agent tool module cannot be imported

#5956

◆ Decision needed · PR description

The TypeScript updateConversation method returns the updated conversation data. Callers receive its ID and title instead of only a success flag.

Original PR title

fix(typescript): resolve updateConversation with the updated conversation

#5955

◆ Decision needed · PR description

The gateway reserves a run slot before it saves a continued chat message. A refused request returns 429 without adding a message that a retry would duplicate.

Original PR title

fix(agent-server): reserve the run slot before a gateway turn saves its message

#5949

◆ Decision needed · PR description

Telemetry keeps the pod’s original deferred_init flag after initialization. Operators can distinguish these pods from servers that started normally.

Original PR title

fix(agent-server): report deferred_init true from initialized deferred pods

#5948

◆ Decision needed · PR description

The gateway returns 409 if another request already uses the same conversation. Each accepted request receives the answer to its own turn.

Original PR title

fix(agent-server): refuse overlapping chat turns on one conversation with 409

#5924

◆ Decision needed · PR description

The server leaves the browser out of server_info.usable_tools when enable_browser is false. Clients no longer offer a tool that conversations cannot use.

Original PR title

fix(agent-server): apply enable_browser to /server_info usable_tools

#5906

◆ Decision needed · PR description

Refresh returns 400 or 422 for an unavailable source, invalid content or a local installation. These cases no longer appear as unhandled server failures.

Original PR title

fix(agent-server): answer 400/422 when refreshing an unfetchable skill or plugin

#5892

◆ Decision needed · PR description

Activation reports applied=false when the agent cannot use model routing. Clients no longer receive an apparent success for a profile that was not activated.

Original PR title

fix(agent-server): report applied=false when meta-profile activation cannot route

#5887

◆ Decision needed · PR description

The server rejects a meta-profile that cannot select a destination. It no longer stores a configuration that makes a paid classifier call with no usable choices.

Original PR title

fix(agent-server): refuse meta-profiles that can never route

#5886

◆ Decision needed · PR description

The OpenAI device-login endpoints return gateway errors for upstream connection failures, timeouts and error responses. Clients can distinguish a provider problem from a local server failure.

Original PR title

fix(agent-server): answer gateway errors when OpenAI device login fails upstream

#5877

◆ Decision needed · PR description

The TypeScript client adds the profile fields the server sends and removes incorrect requirements. Profile editors can read and save the actual API payloads.

Original PR title

fix(ts-client): match agent-profile payload types to the server models

#5876

◆ Decision needed · PR description

The server treats a profile name with or without .json as the same name. Saving it again preserves its ID and keeps active references valid.

Original PR title

fix(agent-server): keep agent profile identity for .json-suffixed names

#5868

◆ Decision needed · PR description

Deleting an LLM profile through its .json name checks existing references. Rename and delete also update active pointers through that alias.

Original PR title

fix(agent-server): guard LLM profile delete through the .json alias

#5866

◆ Decision needed · PR description

The MCP OAuth callback endpoint returns the job status after the job ends. Repeated submissions no longer try to contact a closed callback server.

Original PR title

fix(agent-server): answer replayed MCP OAuth callbacks with the job status

#5865

◆ Decision needed · PR description

The settings endpoint checks active agent and meta-profile references before saving them. It no longer accepts a pointer to a profile that does not exist.

Original PR title

fix(agent-server): refuse PATCH /api/settings pointers to missing profiles

#5859

◆ Decision needed · PR description

The server URL-encodes the folder and token query values. Spaces, ampersands and hash signs no longer make VS Code open the wrong folder.

Original PR title

fix(agent-server): URL-encode the VS Code URL's folder and token

#5854

◆ Decision needed · PR description

The archive API description explains its nested-repository selection. Users can see when files beside the selected repository will be left out.

Original PR title

fix(agent-server): describe nested-repository resolution in archive params

#5852

◆ Decision needed · PR description

Switching back to a profile loads its current configuration. A conversation no longer reuses an old model or key cached before the profile was edited.

Original PR title

fix(sdk): install the edited profile when switch_profile re-switches

#5848

◆ Decision needed · PR description

Git changes requested from a repository subfolder are relative to that subfolder. The response no longer mixes repository paths with subfolder paths.

Original PR title

fix(sdk): list git changes of a repository subdirectory relative to it

#5830

◆ Decision needed · PR description

A live ACP model switch returns 400 if the session does not offer that model. Clients no longer see a server error for a model choice that cannot work.

Original PR title

fix(sdk): refuse a live ACP switch to a model the session does not offer with 400

#5827

◆ Decision needed · PR description

Pending runtime credential bindings are not applied to regular conversations. Those conversations no longer become blocked on credentials they do not use.

Original PR title

fix(agent-server): ignore pending credential bindings for non-ACP conversations

#5821

◆ Decision needed · PR description

The condense endpoint returns 409 if the agent has no condenser that can handle the request. Clients can distinguish this configuration limit from a server failure.

Original PR title

fix(agent-server): answer 409 when condense has no request-handling condenser

#5816

◆ Decision needed · PR description

The server rejects switch_llm and switch_profile for ACP conversations. It no longer reports a successful switch that cannot change the subprocess’s model.

Original PR title

fix(agent-server): refuse switch_llm/switch_profile on ACP conversations

#5805

◆ Decision needed · PR description

The events endpoint returns 422 for assistant, system or tool input roles. It rejects them before creating a system prompt or initializing the agent.

Original PR title

fix(agent-server): reject non-user roles on POST events with 422

#5798

◆ Decision needed · PR description

The SDK reports a validation error when a discriminated-union value is not an object. Invalid secret strings, numbers, booleans or null produce 422 instead of an internal error.

Original PR title

fix(sdk): refuse a non-object discriminated-union input with a ValidationError

#5796

◆ Decision needed · PR description

The settings endpoint rejects an MCP server with neither command nor url. One empty entry no longer prevents tools from valid neighboring entries from loading.

Original PR title

fix(agent-server): reject MCP servers with neither command nor url

#5792

◆ Decision needed · PR description

The workspace cookie includes the server’s path prefix. Browsers behind a prefix proxy can authenticate embedded workspace pages.

Original PR title

fix(agent-server): scope the workspace session cookie to the root path

#5788

◆ Decision needed · PR description

The SDK saves secret, confirmation-policy and security-analyzer changes in conversation state. Resume no longer restores old creation-time values or loses the last secret update.

Original PR title

fix(agent-server): persist secret, policy and analyzer changes in base_state

#5783

◆ Decision needed · PR description

The TypeScript manager sends maxIterations and stuckDetection when it creates a conversation. The server no longer silently uses defaults instead of the caller’s choices.

Original PR title

fix(ts): honor maxIterations and stuckDetection in ConversationManager.createConversation

#5780

◆ Decision needed · PR description

The server avoids slow rich traceback rendering on the event loop when a run fails. Other requests and sockets can remain responsive during error reporting.

Original PR title

fix(agent-server): log failed runs without rendering a rich traceback on the loop

#5778

◆ Decision needed · PR description

The synchronous Bash endpoint collects all stored output and the final exit code. Large output no longer loses earlier chunks or appears successful before completion.

Original PR title

fix(agent-server): return the whole output from execute_bash_command

#5775

◆ Decision needed · PR description

The server refuses to activate or overwrite a profile whose encrypted key is unreadable. It preserves the encrypted value so restoring the original key can recover it.

Original PR title

fix(agent-server): refuse activating or re-saving a profile under a changed cipher key

#5771

◆ Decision needed · PR description

The SDK skips unavailable custom tools and unrecognized stored event types with warnings during resume. A missing module no longer prevents the conversation from loading.

Original PR title

fix(sdk): resume a conversation whose custom tool module is gone

#5769

◆ Decision needed · PR description

The TypeScript callback clients use globalThis.WebSocket when available. They can deliver events in modern Node without calling require inside an ES module.

Original PR title

fix(typescript): use the global WebSocket in the callback socket clients

#5768

◆ Decision needed · PR description

Profile validation uses a short request and retry policy. It also treats an exhausted budget or quota as invalid instead of reporting a usable key.

Original PR title

fix(agent-server): bound profile pre-flight and reject exhausted quotas

#5767

◆ Decision needed · PR description

The server checks the .plugin marketplace manifest before the old fallback path. The Marketplace tab can list the public extensions repository instead of showing no skills.

Original PR title

fix(agent-server): load skills marketplace from .plugin manifest first

#5766

◆ Decision needed · PR description

Each trajectory download uses a separate temporary ZIP file. Parallel downloads no longer overwrite or delete the file another response is sending.

Original PR title

fix(agent-server): give each trajectory download its own temp zip

#5765

◆ Decision needed · PR description

The SDK carries the source cipher and secrets into a fork. A new branch no longer loses its stored LLM key and fails on its first turn.

Original PR title

fix(sdk): keep the source's cipher and secrets on a forked conversation

#5764

◆ Decision needed · PR description

The TypeScript event stream schedules another connection attempt after an error-only handshake failure. It can recover when a server is down or restarting.

Original PR title

fix(typescript): keep reconnecting when a refused handshake fires only error

#5763

◆ Decision needed · PR description

The bridge negotiates a subprotocol with the backend before accepting the browser connection. Apps that require a protocol can complete the handshake.

Original PR title

fix(agent-server): negotiate WebSocket subprotocols through the app-backend bridge

#5762

◆ Decision needed · PR description

Preserve binary downloads

Open (not approved)

The TypeScript remote workspace reads downloads as bytes. Binary files no longer pass through UTF-8 text decoding and return corrupted content.

Original PR title

fix(ts-client): keep binary bytes in RemoteWorkspace downloads

#5761

◆ Decision needed · PR description

The gateway returns the tokens used by the current request, including streamed usage. Clients no longer count all earlier turns again.

Original PR title

fix(agent-server): report per-request usage on continued chat completions

#5758

◆ Decision needed · PR description

The server supports key rotation and refuses writes that would erase values encrypted with a lost key. Existing encrypted settings remain recoverable instead of being replaced with null.

Original PR title

fix(agent-server): support cipher key rotation and refuse writes under a lost key

#5757

◆ Decision needed · PR description

The server closes event and session sockets on delete or sandbox pause. Clients can detect the change and reconnect rather than staying attached to a discarded service.

Original PR title

fix(agent-server): close conversation sockets on delete and sandbox pause

#5756

◆ Decision needed · PR description

The SDK removes a disabled ambient plugin’s skills and MCP servers when it resumes a conversation. It no longer restores those contributions from old saved agent state.

Original PR title

fix(sdk): drop a since-disabled ambient plugin's skills and MCP servers on resume

#5755

◆ Decision needed · PR description

Validation resolves a draft profile’s saved provider connection. A profile without an inline key can pass the same key check used during activation.

Original PR title

fix(agent-server): resolve provider connection in profile validate

#5945

◆ Decision needed · PR description

The server removes the tmux folder it created when it shuts down normally. Repeated starts no longer leave those folders behind.

Original PR title

fix(agent-server): remove the per-server TMUX_TMPDIR on shutdown

#5944

◆ Decision needed · PR description

The sync endpoint reports an error when it cannot fetch repository updates. It no longer describes use of an old cached copy as a successful sync.

Original PR title

fix(agent-server): report a failed skills sync fetch as an error

#5929

◆ Decision needed · PR description

The server only lets proxy headers change the request scheme when trust_forwarded_headers allows it. Untrusted headers no longer change the app bridge’s origin check.

Original PR title

fix(agent-server): tie uvicorn proxy_headers to trust_forwarded_headers

#5921

◆ Decision needed · PR description

The server leaves web-researcher out of the sub-agent list when the browser is disabled. Clients no longer offer a sub-agent with no usable tool.

Original PR title

fix(agent-server): leave web-researcher out of sub-agents when the browser is disabled

#5920

◆ Decision needed · PR description

The app bridge detects a dead backend before it forwards requests or creates sessions. Clients receive a backend status error instead of a misleading container error.

Original PR title

fix(agent-server): stop bridging to a crashed Canvas backend

#5909

◆ Decision needed · PR description

Extension installation accepts github:owner/repo/path. Users can select a folder within the repository through the documented shorthand.

Original PR title

fix(sdk): accept the documented github:owner/repo/<path> install source

#5907

◆ Decision needed · PR description

The server returns no VS Code URL when VS Code is not running. It no longer offers a broken link that contains a session token.

Original PR title

fix(agent-server): don't advertise a VS Code URL while VS Code is not running

#5905

◆ Decision needed · PR description

A Git plugin without a root manifest takes its name from the repository. Its installed name no longer includes the clone cache’s URL hash.

Original PR title

fix(sdk): name a manifest-less git repository plugin after the repository

#5891

◆ Decision needed · PR description

The SDK keeps indentation and trailing blank lines in the original Git content. An unchanged file no longer shows a false diff.

Original PR title

fix(sdk): keep edge whitespace on the original side of a git diff

#5754

◆ Decision needed · PR description

The SDK skips a sub-agent definition that names a missing skill and logs a warning. Other sub-agents still load, and the missing skill no longer breaks the conversation.

Original PR title

fix(sdk): skip sub-agents whose skill is missing instead of failing

Browser and app backends 8

#5923

The app bridge forwards a path query parameter as query data on the root route. It no longer mistakes that value for the backend URL path.

Original PR title

fix(agent-server): forward ?path= on the bare Canvas app-backend root route

#5918

The proxy preserves the client’s body length or chunked framing. Backends that read Content-Length can receive the full request body.

Original PR title

fix(agent-server): keep the client's body framing in proxied requests

#5917

Backend preparation returns 409 when an artifact is not a valid gzip tar archive. The client receives a reason instead of an unhandled 500 error.

Original PR title

fix(agent-server): refuse a non-gzip canvas backend artifact with 409

#5916

The proxy removes the upstream Date and Server headers before the server adds its own. Responses no longer contain duplicate dates or disclose the backend’s server header.

Original PR title

fix(agent-server): drop upstream Date and Server from proxied responses

#5855

In Docker mode, the workspace root accepts its session cookie with or without a trailing slash. Embedded workspace pages no longer fail authentication on the shorter URL.

Original PR title

fix(agent-server): accept the workspace cookie on the Docker-mode workspace root

#5774

The server tracks backend processes across restarts and removes verified orphans. A crash no longer leaves an old backend running beside a new copy on the same data.

Original PR title

fix(agent-server): reap Canvas backends orphaned by a crashed server

#5759

The server checks a live backend again after a failed health probe. A temporary delay no longer leaves a recovered app marked unhealthy until restart.

Original PR title

fix(agent-server): re-probe a Canvas App backend after a missed health probe

Commands 4

#5875

Bash event searches apply the UTC offset in each timestamp. Different timestamp forms for the same instant return the same events.

Original PR title

fix(agent-server): honor UTC offsets in bash event timestamp filters

#5850

The server keeps a conversation loaded while a scoped Bash command runs. Idle cleanup no longer kills the command before it reports an exit code.

Original PR title

fix(agent-server): keep conversations with running scoped bash commands loaded

#5842

Bash event search applies order__gt before the page limit. Polling clients can receive later output chunks and the command’s exit code.

Original PR title

fix(agent-server): apply bash order__gt filter before paging

#5840

Conversation-scoped Bash endpoints return 422 when an ID is not a UUID. They no longer read missing request state and fail with 500.

Original PR title

fix(agent-server): answer 422 for a malformed id on scoped bash routes

Configuration and telemetry 5

#5967

The server reads token and cost totals before it sends the run outcome. Telemetry reports usage ranges instead of “unknown” when totals are available.

Original PR title

fix(agent-server): report real usage buckets in telemetry outcome events

#5964

The API description explains that telemetry uses the server secret when no salt is set. Operators can see why conversation IDs remain linkable across restarts.

Original PR title

fix(agent-server): describe the secret-key fallback of TelemetrySpec.salt

#5951

An OH_*_IS_NONE=1 setting clears a nullable value from the configuration file. The file value no longer overrides an explicit request for null.

Original PR title

fix(agent-server): let OH_*_IS_NONE=1 clear a config file value

#5943

The API description gives the actual event URL, including the conversation ID. It also explains that new events do not restart the flush timer.

Original PR title

fix(agent-server): correct WebhookSpec base_url and flush_delay descriptions

#5797

The server updates its browser-origin checks from the initialization settings. Browsers from those allowed origins can pass the preflight request.

Original PR title

fix(agent-server): apply init-delivered allow_cors_origins to CORS

Conversation state 13

#5973

The server returns 409 when another server owns the conversation. It keeps the previous title, tags and secrets when it cannot save a change.

Original PR title

fix(agent-server): answer 409 and keep state when a write loses ownership

#5954

The run endpoint returns 409 without waiting for a long tool call to finish. The Python remote client can then wait for the existing run without a trigger timeout.

Original PR title

fix(agent-server): answer /run 409 without waiting for the state lock

#5858

A model or profile switch made during an agent step is saved before the endpoint returns. Reads and restarts no longer see the previous model after an acknowledged switch.

Original PR title

fix(sdk): persist a mid-step switch_llm before it returns

#5832

Resuming a goal does not add agent rounds beyond max_iterations. An interrupted judge call no longer causes the agent to exceed the user’s limit.

Original PR title

fix(agent-server): keep resumed goal loops within max_iterations

#5826

The final-response endpoint reads only the conversation’s current branch. After navigation, it no longer returns an answer from an abandoned branch.

Original PR title

fix(agent-server): read agent_final_response from the active branch

#5819

The ask_agent endpoint returns 404 when the conversation does not exist. A missing conversation no longer looks like a model or server failure.

Original PR title

fix(agent-server): return 404 from ask_agent for an unknown conversation

#5814

Pause, interrupt, update and delete return 404 for an unknown conversation ID. Clients no longer receive a misleading bad request or successful update response.

Original PR title

fix(agent-server): return 404 for unknown ids on pause, interrupt, PATCH and DELETE

#5802

The update endpoint returns 422 for a whitespace-only title. It no longer clears the existing title and prevents automatic title generation.

Original PR title

fix(agent-server): reject a whitespace-only conversation title on PATCH

#5795

Batch conversation lookup returns 422 when a request exceeds 99 IDs. The API publishes the limit and enforces it even when Python assertions are disabled.

Original PR title

fix(agent-server): refuse more than 99 batch-get ids with a 422

#5777

A server reads the latest saved metadata when it loads a conversation. It no longer overwrites another server’s newer title, tags or secrets with its startup copy.

Original PR title

fix(agent-server): re-read meta.json when loading a persisted conversation

#5776

The SDK saves changes such as pause while a model call is still in progress. API reads and restarts can see the acknowledged change without waiting for the model.

Original PR title

fix(sdk): persist state changes made while a step waits on the model

#5770

Discriminated-union validation no longer removes kind from the supplied object. Repeated reads of remote agent and security settings remain valid.

Original PR title

fix(sdk): keep discriminated-union validation from mutating its input

Events and streaming 8

#5966

The Python remote client sends streaming chunks to listeners without adding them to state.events. Its cached history matches the server’s stored events.

Original PR title

fix(sdk): keep streamed deltas out of RemoteConversation.state.events

#5965

The Python remote client calls token_callbacks as token chunks arrive. Applications can display the agent’s text while it is generated.

Original PR title

fix(sdk): deliver streamed deltas to RemoteConversation token_callbacks

#5953

The server checks the webhook buffer after a batch finishes sending. It sends another full batch at once instead of waiting for a timer or new events.

Original PR title

fix(agent-server): post webhook events that fill the buffer during an in-flight batch

#5950

The Python remote client calls listeners for stored events recovered after a WebSocket reconnect. A live display no longer misses those events.

Original PR title

fix(sdk): pass events missed during a WebSocket reconnect to RemoteConversation callbacks

#5818

The SDK publishes a user message before the state update that refers to it. Clients that resume from event sequence numbers no longer risk skipping the message.

Original PR title

fix(sdk): publish a user message before its last_user_message_id update

#5803

The server timestamps callback events when it appends them. Timestamp-based history reads no longer miss updates created earlier but stored later.

Original PR title

fix(agent-server): stamp callback events when they are appended

#5773

Event search and count accept names such as MessageEvent. Clients following the API description no longer receive an empty history for existing events.

Original PR title

fix(agent-server): accept short event kinds in events search and count

Files and Git 9

#5931

An upload returns 400 if its target is a directory or a parent is a regular file. The client can distinguish an invalid path from a server failure.

Original PR title

fix(agent-server): answer uploads onto a directory or below a file with 400

#5902

The server writes an upload to a temporary file before replacing the destination. A failed overwrite no longer truncates the previous file.

Original PR title

fix(agent-server): make file upload overwrites atomic

#5864

The workspace registry does not rewrite its file for a no-op request. Deleting an unknown path no longer creates a file or fails because storage is read-only.

Original PR title

fix(agent-server): skip the workspaces save when a write changes nothing

#5857

The SDK compares a deleted file with its original Git content. The Changes view can show the deletion instead of returning “file does not exist”.

Original PR title

fix(sdk): diff a working-tree-deleted file against its base text

#5856

The upload response includes file_size. Python and TypeScript callers can report how many bytes they wrote instead of receiving no size.

Original PR title

fix(agent-server): report the uploaded file_size in the upload response

#5853

Directory search uses a cursor that distinguishes names such as Foo and foo. Clients can load the next page without repeating the same folder forever.

Original PR title

fix(agent-server): page search_subdirs past names that differ only by case

#5782

Git change lists preserve spaces and non-ASCII characters in filenames. One such name no longer breaks the whole Changes view or appears in a damaged escaped form.

Original PR title

fix(git): keep file names verbatim in git changes and commit changes

#5781

Trajectory downloads use the conversation folder chosen during server initialization. Deferred-init servers no longer look in the old launch-time folder.

Original PR title

fix(agent-server): serve trajectories from the init-time conversations path

#5753

Git change lookup checks for a repository below a non-repository folder. A Changes view using the workspace root no longer misses edits in that repository.

Original PR title

fix(sdk): list changes of a repository below a non-repository path

Gateway and ACP 4

#5968

A continued chat request returns 409 when the agent pauses or needs confirmation. The client no longer waits for a timeout.

Original PR title

fix(agent-server): answer 409 when a continued gateway run waits for confirmation

#5926

The subscription status endpoint reports connected=false if OpenAI cannot be reached during a token refresh. It keeps the saved credentials so the connection can recover when the network returns.

Original PR title

fix(agent-server): read an unreachable OpenAI refresh as disconnected

#5812

The TypeScript documentation explains that a pre-run model switch returns 200 and saves the choice for later. It no longer describes a 409 response that the server does not send.

Original PR title

docs(typescript): describe the pre-run 200-and-defer switchAcpModel behaviour

#5811

The SDK rejects empty or whitespace-only model IDs before an ACP session starts. It no longer saves a model choice that a live session would refuse.

Original PR title

fix(sdk): refuse a blank ACP model before the first run

Profiles and secrets 11

#5927

Meta-profile activation returns 409 when the settings file is corrupt or uses another encryption key. The response no longer exposes the file path in an unhandled error.

Original PR title

fix(agent-server): answer 409 for meta-profile activation over a corrupted settings file

#5904

A replacement LLM receives the managed-key refresh hook. A model switch no longer disables the configured refresh and retry after an authentication failure.

Original PR title

fix(agent-server): keep the managed-key refresh hook after an LLM switch

#5898

The secrets endpoint maps invalid agent profiles to 400 and a busy profile store to 503. These cases no longer return an unhandled 500 error.

Original PR title

fix(agent-server): map profile-store errors in scoped secrets list

#5884

The meta-profile store expands ~ in OH_PERSISTENCE_DIR. It writes beside the other settings instead of creating a folder literally named ~.

Original PR title

fix(sdk): expand ~ in OH_PERSISTENCE_DIR for the meta-profile store

#5874

The source documentation names the actual materialize result for a missing default LLM profile. It no longer tells readers to look for a field that is not returned.

Original PR title

fix(agent-server): describe the real materialize report in the seed docstring

#5869

The SDK recognizes authentication status codes even when the provider library calls them BadRequestError. A bad key no longer appears as a general request error.

Original PR title

fix(sdk): classify a BadRequestError carrying HTTP 401/403 as an auth error

#5851

The API description says an invalid secret name returns 422. It now matches the status the GET and DELETE endpoints already return.

Original PR title

fix(agent-server): document 422 for an invalid secret name

#5794

A request waiting for a profile-store lock no longer blocks unrelated requests and sockets. The server can still answer health checks while the store is busy.

Original PR title

fix(agent-server): keep the server responsive while a profile store lock is held

#5786

Provider connection create and update reject blank keys and the redacted placeholder. Clients no longer clear a shared key or save the mask as a real key by accident.

Original PR title

fix(agent-server): reject blank and redacted provider-connection api_key

#5779

The SDK installs the new LLM configuration when switch_llm uses an existing usage_id. The endpoint no longer reports success while keeping the old model.

Original PR title

fix(sdk): install the posted LLM when switch_llm targets a registered usage_id

Tools and extensions 6

#5903

Skills sync clears the marketplace cache. The next catalog request can show the updated repository instead of an old or empty list.

Original PR title

fix(agent-server): clear the skills marketplace cache on sync

#5901

The installer treats unreadable YAML frontmatter as an invalid skill. The API returns 422 instead of exposing an unhandled parser error.

Original PR title

fix(sdk): reject skill installs with unparsable frontmatter as invalid

#5867

The MCP OAuth callback endpoint returns 400 for a non-numeric or out-of-range port. Invalid URLs no longer cause an unhandled server error.

Original PR title

fix(agent-server): reject MCP OAuth callback URLs with a bad port as 400

#5815

Loading the same plugin twice keeps one copy of its hooks. A retry no longer makes each hook run twice for a user message.

Original PR title

fix(sdk): keep one copy of a plugin's hooks when it is loaded twice

#5793

The installer fails if a cached clone cannot check out the requested ref. It no longer replaces an extension with another commit while reporting success.

Original PR title

fix(sdk): fail extension installs whose ref a cached clone cannot check out

TypeScript client 1

#5957

The TypeScript client uses the Git status values that the server sends, such as UPDATED. Applications can compare these values without incorrect type errors.

Original PR title

fix(typescript-client): type GitChange.status with the server's wire values