Skip to content
This repository was archived by the owner on Sep 7, 2026. It is now read-only.

feat(profiles): add ProfilesClient and RemoteConversation.switchLlm - #148

Merged
VascoSch92 merged 4 commits into
mainfrom
vasco/profiles-client
May 9, 2026
Merged

VascoSch92 merged 4 commits into
mainfrom
vasco/profiles-client

Conversation

@VascoSch92

@VascoSch92 VascoSch92 commented May 9, 2026 •

Copy link
Copy Markdown
Member
  • A human has tested these changes.

Summary

  • Add ProfilesClient mirroring the existing thin-client pattern (SettingsClient/SkillsClient): constructor takes { host, apiKey?, timeout? }, holds an HttpClient, and exposes close(). Methods cover the full /api/profiles surface: listProfiles, getProfile, saveProfile, deleteProfile, renameProfile, activateProfile. Path segments go through encodeURIComponent.
  • Support the new X-Expose-Secrets header from agent-sdk #3161 via getProfile(name, { exposeSecrets }), where exposeSecrets is 'encrypted' | 'plaintext'. Header is omitted when not set, preserving the default nulled-api_key behavior.
  • Add corresponding response/request types to models/api.ts (ProfileInfo, ProfileListResponse, ProfileDetailResponse, ProfileMutationResponse, ActivateProfileResponse, SaveProfileRequest, RenameProfileRequest, ExposeSecretsMode) and re-export from index.ts.
  • Wire ProfilesClient into ConversationManager as manager.profiles, including close().
  • Add RemoteConversation.switchLlm(llm) to fill a parity gap with the server's existing POST /api/conversations/{id}/switch_llm endpoint (sibling of the already-wired switchProfile).

Missing — integration tests

This PR ships unit tests only (mocked global.fetch). Integration coverage in src/__tests__/integration/ is not added here. Tracked in OpenHands/software-agent-sdk#4745:

Type

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

@VascoSch92
VascoSch92 marked this pull request as ready for review May 9, 2026 13:53
@VascoSch92
VascoSch92 requested a review from all-hands-bot May 9, 2026 13:54

Copy link
Copy Markdown
Member

Integration Feedback from agent-canvas

I've integrated this PR into the agent-canvas frontend (commit 195e9c3). The ProfilesClient and types work well! Here are a few observations:

Working Great ✅

  • ProfilesClient methods map 1:1 with the agent-server API
  • The GetProfileOptions.exposeSecrets approach is clean
  • ProfileInfo, ProfileListResponse, ProfileDetailResponse, ProfileMutationResponse all match the backend responses

Type Compatibility Notes

  1. SaveProfileRequest.llm is required - The SDK has llm: LLM as a required field. The previous local implementation had llm? (optional) to support a "snapshot current settings" mode. I verified the agent-canvas usage always provides llm, so this is fine for our use case. Just noting in case other consumers need the optional behavior.

  2. ActivateProfileResponse.llm_applied - Good addition! The local implementation incorrectly expected model: string | null which wasn't actually returned by the backend.

  3. LLM.base_url type - SDK uses base_url?: string while the local code sometimes passed base_url: null. Updated to use ...(baseUrlValue ? { base_url: baseUrlValue } : {}) spreading pattern to match the SDK type.

No Missing Features Found

The SDK covers all the ProfilesClient functionality needed by agent-canvas. The integration went smoothly!


This comment was created by an AI agent (OpenHands) on behalf of the user.

@malhotra5 malhotra5 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM!

@VascoSch92
VascoSch92 merged commit e15db92 into main May 9, 2026
6 of 8 checks passed
@github-actions github-actions Bot added the type: feat A new feature label Aug 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

type: feat A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants