fix(sdk): add peer field to session creation methods (#705)
This commit is contained in:
parent
b5f24a6ac5
commit
10f72a7d0d
|
|
@ -60,7 +60,7 @@ repos:
|
|||
language: system
|
||||
files: ^(src/|tests/|sdks/python/|scripts/).*\.py$
|
||||
require_serial: true
|
||||
pass_filenames: false
|
||||
pass_filenames: true
|
||||
|
||||
# Run main application tests
|
||||
- id: pytest-main
|
||||
|
|
|
|||
|
|
@ -243,6 +243,14 @@ class HonchoAio(AsyncMetadataConfigMixin):
|
|||
*,
|
||||
metadata: dict[str, object] | None = None,
|
||||
configuration: SessionConfiguration | None = None,
|
||||
peers: str
|
||||
| PeerBase
|
||||
| tuple[str, SessionPeerConfig]
|
||||
| tuple[PeerBase, SessionPeerConfig]
|
||||
| list[PeerBase | str]
|
||||
| list[tuple[PeerBase | str, SessionPeerConfig]]
|
||||
| list[PeerBase | str | tuple[PeerBase | str, SessionPeerConfig]]
|
||||
| None = None,
|
||||
) -> Session:
|
||||
"""
|
||||
Get or create a session with the given ID asynchronously.
|
||||
|
|
@ -251,6 +259,9 @@ class HonchoAio(AsyncMetadataConfigMixin):
|
|||
id: Unique identifier for the session within the workspace.
|
||||
metadata: Optional metadata dictionary to associate with this session.
|
||||
configuration: Optional configuration to set for this session.
|
||||
peers: Optional peers to attach to the session at creation. Accepts the
|
||||
same shape as Session.add_peers (peer ID string, Peer object, list
|
||||
of either, or tuples with SessionPeerConfig).
|
||||
|
||||
Returns:
|
||||
A Session object with cached values from the API response.
|
||||
|
|
@ -261,6 +272,8 @@ class HonchoAio(AsyncMetadataConfigMixin):
|
|||
body["metadata"] = metadata
|
||||
if configuration is not None:
|
||||
body["configuration"] = configuration.model_dump(exclude_none=True)
|
||||
if peers is not None:
|
||||
body["peers"] = normalize_peers_to_dict(peers)
|
||||
|
||||
data = await self._honcho._async_http_client.post(
|
||||
routes.sessions(self._honcho.workspace_id), body=body
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ from .api_types import (
|
|||
PeerResponse,
|
||||
QueueStatusResponse,
|
||||
SessionConfiguration,
|
||||
SessionPeerConfig,
|
||||
SessionResponse,
|
||||
WorkspaceConfiguration,
|
||||
WorkspaceResponse,
|
||||
|
|
@ -28,7 +29,7 @@ from .mixins import MetadataConfigMixin
|
|||
from .pagination import SyncPage
|
||||
from .peer import Peer
|
||||
from .session import Session
|
||||
from .utils import resolve_id
|
||||
from .utils import normalize_peers_to_dict, resolve_id
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -400,6 +401,17 @@ class Honcho(BaseModel, MetadataConfigMixin): # pyright: ignore[reportUnsafeMul
|
|||
None,
|
||||
description="Optional configuration to set for this session. If set, will get/create session immediately with flags.",
|
||||
),
|
||||
peers: str
|
||||
| PeerBase
|
||||
| tuple[str, SessionPeerConfig]
|
||||
| tuple[PeerBase, SessionPeerConfig]
|
||||
| list[PeerBase | str]
|
||||
| list[tuple[PeerBase | str, SessionPeerConfig]]
|
||||
| list[PeerBase | str | tuple[PeerBase | str, SessionPeerConfig]]
|
||||
| None = Field(
|
||||
None,
|
||||
description="Optional peers to attach to the session at creation. Accepts the same shape as Session.add_peers.",
|
||||
),
|
||||
) -> Session:
|
||||
"""
|
||||
Get or create a session with the given ID.
|
||||
|
|
@ -411,6 +423,9 @@ class Honcho(BaseModel, MetadataConfigMixin): # pyright: ignore[reportUnsafeMul
|
|||
id: Unique identifier for the session within the workspace.
|
||||
metadata: Optional metadata dictionary to associate with this session.
|
||||
configuration: Optional configuration to set for this session.
|
||||
peers: Optional peers to attach to the session at creation. Accepts the
|
||||
same shape as Session.add_peers (peer ID string, Peer object, list
|
||||
of either, or tuples with SessionPeerConfig).
|
||||
|
||||
Returns:
|
||||
A Session object with cached metadata, configuration, created_at, and is_active.
|
||||
|
|
@ -421,6 +436,8 @@ class Honcho(BaseModel, MetadataConfigMixin): # pyright: ignore[reportUnsafeMul
|
|||
body["metadata"] = metadata
|
||||
if configuration is not None:
|
||||
body["configuration"] = configuration.model_dump(exclude_none=True)
|
||||
if peers is not None:
|
||||
body["peers"] = normalize_peers_to_dict(peers)
|
||||
|
||||
data = self._http.post(routes.sessions(self.workspace_id), body=body)
|
||||
session_data = SessionResponse.model_validate(data)
|
||||
|
|
|
|||
|
|
@ -95,6 +95,42 @@ describe('Session', () => {
|
|||
expect(session1.id).toBe(session2.id)
|
||||
expect(session2.metadata).toEqual({ version: 2 })
|
||||
})
|
||||
|
||||
test('creates session with peers from string array', async () => {
|
||||
const session = await client.session('session-with-peers-strings', {
|
||||
peers: ['create-peer-a', 'create-peer-b'],
|
||||
})
|
||||
|
||||
const peers = await session.peers()
|
||||
const ids = peers.map((p) => p.id)
|
||||
expect(ids).toContain('create-peer-a')
|
||||
expect(ids).toContain('create-peer-b')
|
||||
})
|
||||
|
||||
test('creates session with peers from Peer objects', async () => {
|
||||
const peerA = await client.peer('create-obj-peer-a')
|
||||
const peerB = await client.peer('create-obj-peer-b')
|
||||
const session = await client.session('session-with-peer-objects', {
|
||||
peers: [peerA, peerB],
|
||||
})
|
||||
|
||||
const peers = await session.peers()
|
||||
const ids = peers.map((p) => p.id)
|
||||
expect(ids).toContain('create-obj-peer-a')
|
||||
expect(ids).toContain('create-obj-peer-b')
|
||||
})
|
||||
|
||||
test('creates session with peers and per-peer config', async () => {
|
||||
const session = await client.session('session-with-peer-config', {
|
||||
peers: [
|
||||
['create-config-peer', { observeMe: true, observeOthers: false }],
|
||||
],
|
||||
})
|
||||
|
||||
const config = await session.getPeerConfiguration('create-config-peer')
|
||||
expect(config.observeMe).toBe(true)
|
||||
expect(config.observeOthers).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
// ===========================================================================
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import {
|
|||
HonchoConfigSchema,
|
||||
LimitSchema,
|
||||
normalizeListOptions,
|
||||
type PeerAddition,
|
||||
PeerAdditionToApiSchema,
|
||||
type PeerConfig,
|
||||
PeerConfigSchema,
|
||||
PeerIdSchema,
|
||||
|
|
@ -338,6 +340,10 @@ export class Honcho {
|
|||
id: string
|
||||
metadata?: Record<string, unknown>
|
||||
configuration?: SessionConfig
|
||||
peers?: Record<
|
||||
string,
|
||||
{ observe_me?: boolean | null; observe_others?: boolean | null }
|
||||
>
|
||||
}
|
||||
): Promise<SessionResponse> {
|
||||
return this._http.post<SessionResponse>(
|
||||
|
|
@ -347,6 +353,7 @@ export class Honcho {
|
|||
id: params.id,
|
||||
metadata: params.metadata,
|
||||
configuration: sessionConfigToApi(params.configuration),
|
||||
peers: params.peers,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
|
@ -488,10 +495,13 @@ export class Honcho {
|
|||
* @param id - Unique identifier for the session within the workspace. Should be a
|
||||
* stable identifier that can be used consistently to reference the
|
||||
* same conversation
|
||||
* @param metadata - Optional metadata dictionary to associate with this session.
|
||||
* @param options.metadata - Optional metadata dictionary to associate with this session.
|
||||
* If set, will get/create session immediately with metadata.
|
||||
* @param configuration - Optional configuration to set for this session.
|
||||
* @param options.configuration - Optional configuration to set for this session.
|
||||
* If set, will get/create session immediately with flags.
|
||||
* @param options.peers - Optional peers to attach to the session at creation.
|
||||
* Accepts the same shape as `session.addPeers()` (peer ID strings,
|
||||
* Peer objects, arrays of either, or a record with per-peer config).
|
||||
* @returns Promise resolving to a Session object that can be used to add peers,
|
||||
* send messages, and manage conversation context
|
||||
* @throws Error if the session ID is empty or invalid
|
||||
|
|
@ -501,6 +511,7 @@ export class Honcho {
|
|||
options?: {
|
||||
metadata?: SessionMetadata
|
||||
configuration?: SessionConfig
|
||||
peers?: PeerAddition
|
||||
}
|
||||
): Promise<Session> {
|
||||
await this._ensureWorkspace()
|
||||
|
|
@ -511,11 +522,16 @@ export class Honcho {
|
|||
const validatedConfiguration = options?.configuration
|
||||
? SessionConfigSchema.parse(options.configuration)
|
||||
: undefined
|
||||
const validatedPeers =
|
||||
options?.peers !== undefined
|
||||
? PeerAdditionToApiSchema.parse(options.peers)
|
||||
: undefined
|
||||
|
||||
const sessionData = await this._getOrCreateSession(this.workspaceId, {
|
||||
id: validatedId,
|
||||
configuration: validatedConfiguration,
|
||||
metadata: validatedMetadata,
|
||||
peers: validatedPeers,
|
||||
})
|
||||
return new Session(
|
||||
validatedId,
|
||||
|
|
|
|||
|
|
@ -200,6 +200,55 @@ async def test_session_peer_config(client_fixture: tuple[Honcho, str]):
|
|||
assert retrieved_config.observe_others
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_session_create_with_peers(client_fixture: tuple[Honcho, str]):
|
||||
"""
|
||||
Tests creating a session with peers attached in a single call.
|
||||
"""
|
||||
honcho_client, client_type = client_fixture
|
||||
|
||||
if client_type == "async":
|
||||
session = await honcho_client.aio.session(
|
||||
id="test-session-create-peers-async",
|
||||
peers=["create-peer-async-a", "create-peer-async-b"],
|
||||
)
|
||||
assert isinstance(session, Session)
|
||||
peers = await session.aio.peers()
|
||||
peer_ids = {p.id for p in peers}
|
||||
assert "create-peer-async-a" in peer_ids
|
||||
assert "create-peer-async-b" in peer_ids
|
||||
|
||||
config = SessionPeerConfig(observe_me=True, observe_others=False)
|
||||
peer = await honcho_client.aio.peer(id="create-peer-async-config")
|
||||
session_with_config = await honcho_client.aio.session(
|
||||
id="test-session-create-peers-config-async",
|
||||
peers=[(peer, config)],
|
||||
)
|
||||
retrieved = await session_with_config.aio.get_peer_configuration(peer)
|
||||
assert retrieved.observe_me is True
|
||||
assert retrieved.observe_others is False
|
||||
else:
|
||||
session = honcho_client.session(
|
||||
id="test-session-create-peers",
|
||||
peers=["create-peer-a", "create-peer-b"],
|
||||
)
|
||||
assert isinstance(session, Session)
|
||||
peers = session.peers()
|
||||
peer_ids = {p.id for p in peers}
|
||||
assert "create-peer-a" in peer_ids
|
||||
assert "create-peer-b" in peer_ids
|
||||
|
||||
config = SessionPeerConfig(observe_me=True, observe_others=False)
|
||||
peer = honcho_client.peer(id="create-peer-config")
|
||||
session_with_config = honcho_client.session(
|
||||
id="test-session-create-peers-config",
|
||||
peers=[(peer, config)],
|
||||
)
|
||||
retrieved = session_with_config.get_peer_configuration(peer)
|
||||
assert retrieved.observe_me is True
|
||||
assert retrieved.observe_others is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_session_messages(client_fixture: tuple[Honcho, str]):
|
||||
"""
|
||||
|
|
|
|||
Loading…
Reference in New Issue