Skip to content

Commit a5423b5

Browse files
ajspigVVoruganticlaude
authored
ts SDK fix: adding strict checking (plastic-labs#421)
* fix: adding strict checking and updating readme * chore: changelog and version * fix: Add strict validation to all Python and TypeScript classes * fix: Address Code Rabit Comments * fix: duplicate searchQuery param in typescript session.context() * feat: add created_at, is_active fields, and get_message method * feat: Add pagintion params to sdk * fix: Remove lazy initalization behavior from sdks * fix: Address File Upload Validation, add compatibility shims, address review comments * chore: Docs updates * fix: Convert session config from API format in Peer.sessions() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Pass all args to Session constructor in Peer.sessions() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: Preserve createdAt in Peer.refresh(), pass all data in session.peers() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: changelog for ts * fix: Review Comments * fix: Add createAt and to peers call --------- Co-authored-by: Vineeth Voruganti <13438633+VVoruganti@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e9ee9d9 commit a5423b5

34 files changed

Lines changed: 2315 additions & 537 deletions

docs/changelog/compatibility-guide.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ This guide helps you match the right SDK version to your Honcho API version. New
1010

1111
<CardGroup cols={2}>
1212
<Card title="TypeScript SDK" icon="js">
13-
**Latest:** v2.0.1
13+
**Latest:** v2.1.0
1414

1515
```bash
1616
npm install @honcho-ai/sdk
1717
```
1818
</Card>
1919
<Card title="Python SDK" icon="python">
20-
**Latest:** v2.0.1
20+
**Latest:** v2.1.0
2121

2222
```bash
2323
pip install honcho-ai
@@ -30,7 +30,7 @@ This guide helps you match the right SDK version to your Honcho API version. New
3030

3131
| Honcho API Version | TypeScript SDK | Python SDK |
3232
|-------------------|---------------|------------|
33-
| v3.0.3 (Current) | v2.0.1 | v2.0.1 |
33+
| v3.0.3 (Current) | v2.1.0 | v2.1.0 |
3434
| v3.0.2 | v2.0.0+ | v2.0.0+ |
3535
| v3.0.1 | v2.0.0+ | v2.0.0+ |
3636
| v3.0.0 | v2.0.0+ | v2.0.0+ |

docs/changelog/introduction.mdx

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,30 @@ Welcome to the Honcho changelog! This section documents all notable changes to t
524524

525525
<Tab title="Python SDK">
526526
[Python SDK](https://pypi.org/project/honcho-ai/)
527-
<Update label="v2.0.1 (Current)">
527+
<Update label="v2.1.0 (Current)">
528+
### Added
529+
530+
- `created_at` property on `Peer` and `Session` objects
531+
- `is_active` property on `Session` objects
532+
- `get_message(message_id)` method on `Session` (sync and async) to fetch a single message by ID
533+
- `page`, `size`, and `reverse` pagination parameters on all list methods
534+
535+
### Changed
536+
537+
- **Breaking**: `peer()` and `session()` now always make a get-or-create API call — no more lazy initialization
538+
- Response configuration models now tolerate unknown fields from newer servers for forward compatibility
539+
540+
### Fixed
541+
542+
- Sync and async `Session.get_metadata()`, `get_configuration()`, and `refresh()` now refresh cached `created_at` and `is_active` values along with metadata and configuration
543+
- `honcho.__version__` now derives from package metadata, with a source-checkout fallback, so it stays aligned with released package versions
544+
</Update>
545+
<Update label="v2.0.2">
546+
### Changed
547+
548+
- All input models now reject unknown fields via strict Pydantic validation (`extra="forbid"`). Previously, misspelled or extraneous fields were silently ignored. Now a `ValidationError` is raised with the unrecognized field name.
549+
</Update>
550+
<Update label="v2.0.1">
528551
### Added
529552

530553
- `set_peer_card` method
@@ -638,7 +661,54 @@ Welcome to the Honcho changelog! This section documents all notable changes to t
638661

639662
<Tab title="TypeScript SDK">
640663
[TypeScript SDK](https://www.npmjs.com/package/@honcho-ai/sdk)
641-
<Update label="v2.0.1 (Current)">
664+
<Update label="v2.1.0 (Current)">
665+
### Added
666+
667+
- `createdAt` property on `Peer` and `Session` wrapper objects
668+
- `isActive` property on `Session` wrapper objects
669+
- `getMessage(messageId)` method on `Session` to fetch a single message by ID
670+
- `Peer.representation()`, `Session.representation()`, and `Session.context()` now accept `Message` objects for `searchQuery`
671+
- `page`, `size`, and `reverse` pagination controls on all list methods
672+
673+
### Changed
674+
675+
- **Breaking**: `searchQuery` removed from top-level `context()` options — use `representationOptions.searchQuery` instead:
676+
```typescript
677+
// Before (v2.0.x)
678+
await session.context({ searchQuery: "..." });
679+
// After (v2.1.0)
680+
await session.context({ representationOptions: { searchQuery: "..." } });
681+
```
682+
- List methods (`peers()`, `sessions()`, `messages()`, `workspaces()`) support both the new options object and the legacy raw-filter form
683+
- Representation search options now accept strings and content-like objects, including `Message` instances, while rejecting whitespace-only or invalid runtime inputs
684+
- **Breaking**: `peer()` and `session()` now always make a get-or-create API call — no more lazy initialization. If you relied on constructing SDK objects without triggering a network request, note that every `peer()` and `session()` call now hits the API:
685+
```typescript
686+
// Before (v2.0.x) — no API call
687+
const session = honcho.session("my-session");
688+
// After (v2.1.0) — makes a get-or-create API call
689+
const session = await honcho.session("my-session");
690+
```
691+
- Response configuration models now tolerate unknown fields from newer servers for forward compatibility
692+
- Moved `@types/node` from `dependencies` to `devDependencies`
693+
694+
### Fixed
695+
696+
- `uploadFile()` now rejects unsupported top-level binary/object inputs and only validates inputs the serializer can actually upload
697+
- `uploadFile()` now serializes message configuration using API field names, matching `addMessages()`
698+
- Session fetch methods now refresh cached `createdAt` and `isActive` values alongside metadata and configuration
699+
</Update>
700+
<Update label="v2.0.2">
701+
### Changed
702+
703+
- Client constructor now rejects unknown options via `.strict()` Zod validation. Previously, misspelled options (e.g., `baseUrl` instead of `baseURL`) were silently ignored, causing the SDK to fall back to defaults. Now a `ZodError` is thrown with the unrecognized key name.
704+
- All input schemas now use `.strict()` validation to reject unknown fields.
705+
- `FileUploadSchema.configuration` now uses `MessageConfigurationSchema` instead of open record type.
706+
707+
### Fixed
708+
709+
- README example used `baseUrl` instead of `baseURL`.
710+
</Update>
711+
<Update label="v2.0.1">
642712
### Added
643713

644714
- `setPeerCard` method

docs/v2/documentation/core-concepts/configuration.mdx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,20 @@ import { Honcho } from "@honcho-ai/sdk";
353353
```
354354
</CodeGroup>
355355

356+
### Observation and Peer Join Order
357+
358+
Reasoning tasks are scheduled at the time a message is created, based on which peers are in the session **at that moment**. Honcho does not retroactively schedule reasoning for peers that join later.
359+
360+
This means:
361+
362+
- If Peer C joins a session **after** messages from Peer A and Peer B have already been sent, Peer C will **not** receive reasoning tasks for those earlier messages—even if Peer C has `observe_others` enabled.
363+
- Peer C will only begin observing new messages sent after they join the session.
364+
- Similarly, if a peer leaves a session, they stop being included as an observer for any messages sent after their departure.
365+
366+
<Warning>
367+
There is no retroactive reasoning. If your application needs an observer peer to reason about prior conversation history, add the peer to the session **before** messages are sent. Alternatively use the .chat() endpoint to include the conversation history in the agent's context, regardless of if they were reasoned against or not
368+
</Warning>
369+
356370
## Full Configuration Schema Reference
357371

358372
### Workspace & Session Configuration

docs/v3/documentation/features/advanced/representation-scopes.mdx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,20 @@ Directional representations update automatically through the reasoning pipeline
266266

267267
The pipeline respects scoping—Honcho's representations reason over messages across all sessions, while directional representations only reason over messages from sessions where the observer was an active participant.
268268

269+
### Peer Join Order Matters
270+
271+
Reasoning tasks are scheduled at the time a message is created, based on which peers are in the session **at that moment**. Honcho does not retroactively schedule reasoning for peers that join later.
272+
273+
This means:
274+
275+
- If Peer C joins a session **after** messages from Peer A and Peer B have already been sent, Peer C will **not** receive reasoning tasks for those earlier messages—even if Peer C has `observe_others=true`.
276+
- Peer C will only begin observing new messages sent after they join the session.
277+
- Similarly, if a peer leaves a session, they stop being included as an observer for any messages sent after their departure.
278+
279+
<Warning>
280+
There is no retroactive reasoning. If your application needs an observer peer to reason about prior conversation history, add the peer to the session **before** messages are sent. Alternatively, use `peer.chat()` to include conversation history in the agent's context whether or not those messages were previously reasoned over.
281+
</Warning>
282+
269283
<Note>
270284
Conclusions are cached for fast retrieval. Use `representation()` to retrieve stored conclusions for dashboards and analytics. Use `peer.chat()` when you need query-specific reasoning with natural language.
271285
</Note>

docs/v3/documentation/features/get-context.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ context = session.context(
165165
const context = await session.context({
166166
tokens: 2000,
167167
peerTarget: "user-123",
168-
searchQuery: "What are my coding preferences?",
169168
representationOptions: {
169+
searchQuery: "What are my coding preferences?",
170170
searchTopK: 10, // Number of relevant conclusions to fetch
171171
searchMaxDistance: 0.8, // Max semantic distance (0.0-1.0)
172172
includeMostFrequent: true, // Include most frequent conclusions

docs/v3/documentation/reference/sdk.mdx

Lines changed: 66 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,14 @@ const session = await honcho.session(id);
218218
// List all peers in workspace (returns Page<Peer>)
219219
const peers = await honcho.peers();
220220

221+
// List with pagination and filtering
222+
const filtered = await honcho.peers({
223+
filters: { metadata: { role: "user" } },
224+
page: 1,
225+
size: 25,
226+
reverse: true
227+
});
228+
221229
// List all sessions in workspace (returns Page<Session>)
222230
const sessions = await honcho.sessions();
223231

@@ -234,7 +242,7 @@ const workspaces = await honcho.workspaces();
234242
</CodeGroup>
235243

236244
<Info>
237-
Peer and session creation is **lazy** - no API calls are made until you actually use the peer or session.
245+
`peer()` and `session()` always make a get-or-create API call, returning objects with cached metadata, configuration, and timestamps.
238246
</Info>
239247

240248
### Peer
@@ -243,7 +251,7 @@ Represents an entity that can participate in conversations:
243251

244252
<CodeGroup>
245253
```python Python
246-
# Create peers (lazy creation - no API call yet)
254+
# Create peers (get-or-create API call)
247255
alice = honcho.peer("alice")
248256
assistant = honcho.peer("assistant")
249257

@@ -254,6 +262,7 @@ alice = honcho.peer("bob", config={"role": "user", "active": True}, metadata={"l
254262
# Peer properties
255263
print(f"Peer ID: {alice.id}")
256264
print(f"Workspace: {alice.workspace_id}")
265+
print(f"Created: {alice.created_at}") # Available after API fetch
257266

258267
# Chat with peer's representations (supports streaming)
259268
response = alice.chat("What did I have for breakfast?")
@@ -305,6 +314,7 @@ const assistant = await honcho.peer("assistant");
305314

306315
// Peer properties
307316
console.log(`Peer ID: ${alice.id}`);
317+
console.log(`Created: ${alice.createdAt}`); // Available after API fetch
308318

309319
// Chat with peer's representations (supports streaming)
310320
const response = await alice.chat("What did I have for breakfast?");
@@ -551,7 +561,7 @@ Manages multi-party conversations:
551561

552562
<CodeGroup>
553563
```python Python
554-
# Create session (like peers, lazy creation)
564+
# Create session (get-or-create API call)
555565
session = honcho.session("conversation-1")
556566

557567
# Create with immediate configuration
@@ -561,6 +571,8 @@ session = honcho.session("meeting-1", config={"type": "meeting", "max_peers": 10
561571
# Session properties
562572
print(f"Session ID: {session.id}")
563573
print(f"Workspace: {session.workspace_id}")
574+
print(f"Created: {session.created_at}") # Available after API fetch
575+
print(f"Active: {session.is_active}") # Available after API fetch
564576

565577
# Peer management
566578
session.add_peers([alice, assistant])
@@ -579,8 +591,12 @@ session.add_messages([
579591
assistant.message("Hi Alice! How can I help today?")
580592
])
581593

582-
# Get messages
594+
# Get messages (with optional pagination)
583595
messages = session.messages()
596+
messages = session.messages(page=1, size=100, reverse=True)
597+
598+
# Get a single message by ID
599+
message = session.get_message("message-id")
584600

585601
# Get conversation context
586602
context = session.context(summary=True, tokens=2000)
@@ -641,6 +657,8 @@ const session = await honcho.session("conversation-1");
641657

642658
// Session properties
643659
console.log(`Session ID: ${session.id}`);
660+
console.log(`Created: ${session.createdAt}`); // Available after API fetch
661+
console.log(`Active: ${session.isActive}`); // Available after API fetch
644662

645663
// Peer management
646664
await session.addPeers([alice, assistant]);
@@ -658,8 +676,12 @@ await session.addMessages([
658676
assistant.message("Hi Alice! How can I help today?")
659677
]);
660678

661-
// Get messages
679+
// Get messages (with optional pagination)
662680
const messages = await session.messages();
681+
const paged = await session.messages({ page: 1, size: 100, reverse: true });
682+
683+
// Get a single message by ID
684+
const message = await session.getMessage("message-id");
663685

664686
// Get conversation context
665687
const context = await session.context({ summary: true, tokens: 2000 });
@@ -668,10 +690,10 @@ const context = await session.context({ summary: true, tokens: 2000 });
668690
const richContext = await session.context({
669691
tokens: 2000,
670692
peerTarget: "user",
671-
searchQuery: "What are my preferences?",
672693
peerPerspective: "assistant",
673694
limitToSession: true,
674695
representationOptions: {
696+
searchQuery: "What are my preferences?",
675697
searchTopK: 10,
676698
searchMaxDistance: 0.8,
677699
includeMostFrequent: true,
@@ -811,12 +833,12 @@ The SessionContext object has the following structure:
811833
| `tokens` | `int` | Maximum tokens to include |
812834
| `peer_target` | `str` | Peer ID to get representation for |
813835
| `peer_perspective` | `str` | Peer ID for perspective (requires peer_target) |
814-
| `search_query` | `str` or `Message` | Query string or Message object for semantic search |
815836
| `limit_to_session` | `bool` | Limit representation to session only |
816-
| `search_top_k` | `int` | Number of semantic search results (1-100) |
817-
| `search_max_distance` | `float` | Max semantic distance (0.0-1.0) |
818-
| `include_most_frequent` | `bool` | Include most frequent conclusions |
819-
| `max_conclusions` | `int` | Max conclusions to include (1-100) |
837+
| `representationOptions.searchQuery` | `str` or `Message` | Query string or Message object for semantic search |
838+
| `representationOptions.searchTopK` | `int` | Number of semantic search results (1-100) |
839+
| `representationOptions.searchMaxDistance` | `float` | Max semantic distance (0.0-1.0) |
840+
| `representationOptions.includeMostFrequent` | `bool` | Include most frequent conclusions |
841+
| `representationOptions.maxConclusions` | `int` | Max conclusions to include (1-100) |
820842

821843
## Advanced Usage
822844

@@ -988,23 +1010,46 @@ const actionItems = await session.messages({
9881010

9891011
### Pagination
9901012

1013+
All list methods support `page`, `size`, and `reverse` parameters:
1014+
9911015
<CodeGroup>
9921016
```python Python
993-
# Iterate through all sessions
1017+
# Default pagination (page 1, size 50)
9941018
for session in honcho.sessions():
9951019
print(f"Session: {session.id}")
9961020

997-
# Iterate through session messages
998-
for message in session.messages():
999-
print(f" {message.peer_id}: {message.content}")
1021+
# Custom page size
1022+
for message in session.messages(size=100):
1023+
print(f" {message.peer_id}: {message.content}")
1024+
1025+
# Start at a specific page
1026+
page3 = session.messages(page=3, size=25)
1027+
1028+
# Reverse ordering
1029+
recent_first = session.messages(reverse=True)
1030+
1031+
# Combine with filters
1032+
filtered = session.messages(filters={"peer_id": "alice"}, size=10)
10001033
```
10011034

10021035
```typescript TypeScript
1003-
// Get paginated results
1036+
// Default pagination (page 1, size 50)
10041037
const peersPage = await honcho.peers();
10051038

1006-
// Iterate through all items
1007-
for await (const peer of peersPage) {
1039+
// Custom page size and filtering
1040+
const filtered = await honcho.peers({
1041+
filters: { metadata: { role: "user" } },
1042+
size: 25
1043+
});
1044+
1045+
// Start at a specific page
1046+
const page3 = await session.messages({ page: 3, size: 25 });
1047+
1048+
// Reverse ordering
1049+
const recent = await session.messages({ reverse: true });
1050+
1051+
// Iterate through all items (auto-paginates)
1052+
for await (const peer of await honcho.peers()) {
10081053
console.log(`Peer: ${peer.id}`);
10091054
}
10101055

@@ -1048,8 +1093,8 @@ const supportAgent = await honcho.peer(`agent-${agentId}`);
10481093

10491094
<CodeGroup>
10501095
```python Python
1051-
# Lazy creation - no API calls until needed
1052-
peers = [honcho.peer(f"user-{i}") for i in range(100)] # Fast
1096+
# Create peers (each makes a get-or-create call)
1097+
peers = [honcho.peer(f"user-{i}") for i in range(100)]
10531098

10541099
# Batch operations when possible
10551100
session.add_messages([peer.message(f"Message {i}") for i, peer in enumerate(peers)])
@@ -1059,7 +1104,7 @@ context = session.context(tokens=1500) # Limit context size
10591104
```
10601105

10611106
```typescript TypeScript
1062-
// Lazy creation - no API calls until needed
1107+
// Create peers (each makes a get-or-create call)
10631108
const peers = await Promise.all(
10641109
Array.from({ length: 100 }, (_, i) => honcho.peer(`user-${i}`))
10651110
);

0 commit comments

Comments
 (0)