feat: add set peer card to SDK, bump version, document

This commit is contained in:
Benjamin McCormick 2026-02-05 17:01:04 -05:00
parent e93e57175e
commit f531c3f095
11 changed files with 225 additions and 17 deletions

View File

@ -4,27 +4,23 @@ description: "Compatibility guide for Honcho's SDKs and API"
icon: "shield-check"
---
This guide helps you understand which versions of Honcho's API are compatible with which SDK versions.
This guide helps you match the right SDK version to your Honcho API version. Newer SDK patch versions are always backward-compatible within the same major version — install the latest patch for your range.
## Version Compatibility
### Honcho API v3.0.2 (Current)
## Current Versions
<CardGroup cols={2}>
<Card title="TypeScript SDK" icon="js">
**Compatible Version:** v2.0.0
**Latest:** v2.0.1
Install with:
```bash
npm install @honcho-ai/sdk@2.0.0
npm install @honcho-ai/sdk
```
</Card>
<Card title="Python SDK" icon="python">
**Compatible Version:** v2.0.0
**Latest:** v2.0.1
Install with:
```bash
pip install honcho-ai==2.0.0
pip install honcho-ai
```
</Card>
</CardGroup>
@ -34,9 +30,9 @@ This guide helps you understand which versions of Honcho's API are compatible wi
| Honcho API Version | TypeScript SDK | Python SDK |
|-------------------|---------------|------------|
| v3.0.2 (Current) | v2.0.0 | v2.0.0 |
| v3.0.1 | v2.0.0 | v2.0.0 |
| v3.0.0 | v2.0.0 | v2.0.0 |
| v3.0.2 (Current) | v2.0.0+ | v2.0.0+ |
| v3.0.1 | v2.0.0+ | v2.0.0+ |
| v3.0.0 | v2.0.0+ | v2.0.0+ |
| v2.5.1 | v1.6.0 | v1.6.0 |
| v2.5.0 | v1.6.0 | v1.6.0 |
| v2.4.3 | v1.5.0 | v1.5.0 |

View File

@ -1,6 +1,6 @@
[project]
name = "honcho-ai"
version = "2.0.0"
version = "2.0.1"
description = "Official DX Optimized Python SDK for Honcho"
dynamic = ["readme"]
license = "Apache-2.0"

View File

@ -66,7 +66,7 @@ from .types import (
DialecticStreamResponse,
)
__version__ = "2.0.0"
__version__ = "2.0.1"
__author__ = "Plastic Labs"
__email__ = "hello@plasticlabs.ai"

View File

@ -604,6 +604,25 @@ class PeerAio(AsyncMetadataConfigMixin):
response = PeerCardResponse.model_validate(data)
return response.peer_card
@validate_call(config=ConfigDict(arbitrary_types_allowed=True))
async def set_card(
self,
peer_card: list[str],
target: str | PeerBase | None = None,
) -> list[str] | None:
"""Set the peer card asynchronously."""
await self._peer._honcho._ensure_workspace_async()
target_id = resolve_id(target)
query = {"target": target_id} if target_id else None
data = await self._peer._honcho._async_http_client.put(
routes.peer_card(self._peer.workspace_id, self._peer.id),
body={"peer_card": peer_card},
query=query,
)
response = PeerCardResponse.model_validate(data)
return response.peer_card
@validate_call(config=ConfigDict(arbitrary_types_allowed=True))
async def representation(
self,

View File

@ -476,6 +476,38 @@ class Peer(PeerBase, MetadataConfigMixin):
return response.peer_card
@validate_call(config=ConfigDict(arbitrary_types_allowed=True))
def set_card(
self,
peer_card: list[str],
target: str | PeerBase | None = None,
) -> list[str] | None:
"""
Set the peer card for this peer.
Makes an API call to set the peer card. If a target is provided, sets this
peer's local card of the target peer.
Args:
peer_card: A list of strings to set as the peer card.
target: Optional target peer for local card. If provided, sets this
peer's card of the target peer. Can be a Peer object or peer ID string.
Returns:
A list of strings representing the updated peer card, or None if none is available
"""
self._honcho._ensure_workspace()
target_id = resolve_id(target)
query = {"target": target_id} if target_id else None
data = self._honcho._http.put(
routes.peer_card(self.workspace_id, self.id),
body={"peer_card": peer_card},
query=query,
)
response = PeerCardResponse.model_validate(data)
return response.peer_card
@validate_call(config=ConfigDict(arbitrary_types_allowed=True))
def representation(
self,

View File

@ -430,6 +430,48 @@ describe('Peer', () => {
})
})
// ===========================================================================
// Set Peer Card (PUT /peers/:id/card)
// ===========================================================================
describe('PUT /peers/:id/card', () => {
test('setCard sets and returns peer card', async () => {
const peer = await client.peer('setcard-peer')
const cardData = ['fact one', 'fact two']
const result = await peer.setCard(cardData)
expect(result).toEqual(cardData)
// Verify with get
const card = await peer.card()
expect(card).toEqual(cardData)
})
test('setCard with target peer', async () => {
const observer = await client.peer('setcard-observer')
const observed = await client.peer('setcard-observed')
const cardData = ['target likes TypeScript', 'target is clever']
const result = await observer.setCard(cardData, observed)
expect(result).toEqual(cardData)
// Verify with get
const card = await observer.card(observed)
expect(card).toEqual(cardData)
})
test('setCard with target ID string', async () => {
const peer = await client.peer('setcard-string-peer')
const cardData = ['some fact']
const result = await peer.setCard(cardData, 'setcard-string-target')
expect(result).toEqual(cardData)
})
})
// ===========================================================================
// Peer Context (POST /peers/:id/context)
// ===========================================================================

View File

@ -1,6 +1,6 @@
{
"name": "@honcho-ai/sdk",
"version": "2.0.0",
"version": "2.0.1",
"description": "Official DX Optimized TypeScript SDK for Honcho",
"author": "Plastic Labs <hello@plasticlabs.ai>",
"license": "Apache-2.0",

View File

@ -295,6 +295,18 @@ export class Peer {
)
}
private async _setCard(params: {
peer_card: string[]
target?: string
}): Promise<PeerCardResponse> {
await this._ensureWorkspace()
const { peer_card, ...query } = params
return this._http.put<PeerCardResponse>(
`/${API_VERSION}/workspaces/${this.workspaceId}/peers/${this.id}/card`,
{ body: { peer_card }, query }
)
}
// ===========================================================================
// Public Methods
// ===========================================================================
@ -662,6 +674,30 @@ export class Peer {
return response.peer_card
}
/**
* Set the peer card for this peer.
*
* Makes an API call to set the peer card. If a target is provided, sets this
* peer's local card of the target peer.
*
* @param peerCard - An array of strings to set as the peer card.
* @param target - Optional target peer for local card. If provided, sets this
* peer's card of the target peer. Can be a Peer object or peer ID string.
* @returns Promise resolving to an array of strings containing the updated peer card items,
* or null if no peer card exists
*/
async setCard(
peerCard: string[],
target?: string | Peer
): Promise<string[] | null> {
const validatedTarget = CardTargetSchema.parse(target)
const response = await this._setCard({
peer_card: peerCard,
target: validatedTarget,
})
return response.peer_card
}
/**
* Get a subset of Honcho's Representation of a peer.
*

View File

@ -909,3 +909,52 @@ async def test_get_peer_card_with_data(
assert response.status_code == 200
data = response.json()
assert data["peer_card"] == target_card_content
def test_set_peer_card(client: TestClient, sample_data: tuple[Workspace, Peer]):
"""Test setting peer cards via the PUT endpoint."""
test_workspace, observer_peer = sample_data
# Create a target peer
target_peer_name = str(generate_nanoid())
response = client.post(
f"/v3/workspaces/{test_workspace.name}/peers",
json={"name": target_peer_name},
)
assert response.status_code in [200, 201]
# Set the observer's own card
self_card = ["I am a test peer", "I like writing tests"]
response = client.put(
f"/v3/workspaces/{test_workspace.name}/peers/{observer_peer.name}/card",
json={"peer_card": self_card},
)
assert response.status_code == 200
data = response.json()
assert data["peer_card"] == self_card
# Verify with GET
response = client.get(
f"/v3/workspaces/{test_workspace.name}/peers/{observer_peer.name}/card"
)
assert response.status_code == 200
assert response.json()["peer_card"] == self_card
# Set a card for the target peer
target_card = ["Target is helpful", "Target knows Python"]
response = client.put(
f"/v3/workspaces/{test_workspace.name}/peers/{observer_peer.name}/card",
params={"target": target_peer_name},
json={"peer_card": target_card},
)
assert response.status_code == 200
data = response.json()
assert data["peer_card"] == target_card
# Verify with GET
response = client.get(
f"/v3/workspaces/{test_workspace.name}/peers/{observer_peer.name}/card",
params={"target": target_peer_name},
)
assert response.status_code == 200
assert response.json()["peer_card"] == target_card

View File

@ -104,3 +104,37 @@ def test_message_and_chat_operations(honcho_test_client: Honcho):
# This is a mock response from the agent
_response = user.chat("What did I ask about?")
def test_peer_card_operations(honcho_test_client: Honcho):
"""
Tests setting and getting peer cards.
"""
peer = honcho_test_client.peer(id="card-test-peer")
target = honcho_test_client.peer(id="card-test-target")
# Initially card should be None
card = peer.card()
assert card is None
# Set own card
own_card = ["I am a helpful assistant", "I enjoy learning"]
result = peer.set_card(own_card)
assert result == own_card
# Verify with get
card = peer.card()
assert card == own_card
# Set card for target
target_card = ["Target likes Python", "Target is friendly"]
result = peer.set_card(target_card, target=target)
assert result == target_card
# Verify with get
card = peer.card(target=target)
assert card == target_card
# Own card should still be unchanged
card = peer.card()
assert card == own_card

View File

@ -1136,7 +1136,7 @@ dev = [
[[package]]
name = "honcho-ai"
version = "2.0.0"
version = "2.0.1"
source = { editable = "sdks/python" }
dependencies = [
{ name = "httpx" },