diff --git a/.claude/skills/migrate-honcho-py/MIGRATION-CHECKLIST.md b/.claude/skills/migrate-honcho-py/MIGRATION-CHECKLIST.md index 7f0b9750..5a2d01ff 100644 --- a/.claude/skills/migrate-honcho-py/MIGRATION-CHECKLIST.md +++ b/.claude/skills/migrate-honcho-py/MIGRATION-CHECKLIST.md @@ -85,6 +85,7 @@ Use this checklist to track migration progress. Copy into your working notes and - [ ] `include_most_derived=` → `include_most_frequent=` - [ ] `max_observations=` → `max_conclusions=` +- [ ] `last_user_message=` → `search_query=` ## Return Type Changes diff --git a/.claude/skills/migrate-honcho-py/SKILL.md b/.claude/skills/migrate-honcho-py/SKILL.md index 1ed11c9c..57c59fa7 100644 --- a/.claude/skills/migrate-honcho-py/SKILL.md +++ b/.claude/skills/migrate-honcho-py/SKILL.md @@ -225,6 +225,7 @@ if card: | `chat(stream=True)` | `chat_stream()` | | `include_most_derived=` | `include_most_frequent=` | | `max_observations=` | `max_conclusions=` | +| `last_user_message=` | `search_query=` | | `config=` | `configuration=` | | `PeerContext` | `PeerContextResponse` | | `DeriverStatus` | `QueueStatusResponse` | diff --git a/.claude/skills/migrate-honcho-ts/DETAILED-CHANGES.md b/.claude/skills/migrate-honcho-ts/DETAILED-CHANGES.md index 776b341b..76273d34 100644 --- a/.claude/skills/migrate-honcho-ts/DETAILED-CHANGES.md +++ b/.claude/skills/migrate-honcho-ts/DETAILED-CHANGES.md @@ -186,6 +186,7 @@ const ctx = await session.getContext({ summary: true, peerTarget: user, peerPerspective: assistant, + lastUserMessage: "What are my preferences?", representationOptions: { maxObservations: 50, includeMostDerived: true @@ -197,6 +198,7 @@ const ctx = await session.context({ summary: true, peerTarget: user, peerPerspective: assistant, + searchQuery: "What are my preferences?", representationOptions: { maxConclusions: 50, includeMostFrequent: true diff --git a/.claude/skills/migrate-honcho-ts/MIGRATION-CHECKLIST.md b/.claude/skills/migrate-honcho-ts/MIGRATION-CHECKLIST.md index 78fcc6bd..6adcf94b 100644 --- a/.claude/skills/migrate-honcho-ts/MIGRATION-CHECKLIST.md +++ b/.claude/skills/migrate-honcho-ts/MIGRATION-CHECKLIST.md @@ -49,6 +49,7 @@ Use this checklist to track migration progress. Copy into your working notes and - [ ] Rename `maxObservations` → `maxConclusions` - [ ] Rename `includeMostDerived` → `includeMostFrequent` +- [ ] Rename `lastUserMessage` → `searchQuery` - [ ] Rename `Observation` type → `Conclusion` - [ ] Rename `ObservationScope` type → `ConclusionScope` diff --git a/.claude/skills/migrate-honcho-ts/SKILL.md b/.claude/skills/migrate-honcho-ts/SKILL.md index 5a45e14f..876cc5f9 100644 --- a/.claude/skills/migrate-honcho-ts/SKILL.md +++ b/.claude/skills/migrate-honcho-ts/SKILL.md @@ -175,6 +175,7 @@ await session.updateMessage(message, metadata) | `{ timeoutMs: 60000 }` | `{ timeout: 60 }` | | `{ maxObservations: 50 }` | `{ maxConclusions: 50 }` | | `{ includeMostDerived }` | `{ includeMostFrequent }` | +| `{ lastUserMessage }` | `{ searchQuery }` | | `{ config: ... }` | `{ configuration: ... }` | | `message.peer_id` | `message.peerId` | | `message.created_at` | `message.createdAt` | diff --git a/README.md b/README.md index d9684333..5baa61f4 100644 --- a/README.md +++ b/README.md @@ -44,26 +44,23 @@ poetry add honcho-ai ```python from honcho import Honcho -####### Storing Data in Honcho - # 1. Initialize your Honcho client honcho = Honcho(workspace_id="my-app-testing") -# 2.. Initialize Peers +# 2. Initialize peers alice = honcho.peer("alice") tutor = honcho.peer("tutor") -# 3. Make a Session and send messages +# 3. Create a session and add messages session = honcho.session("session-1") - -session.add_messages([ - alice.message("Hey there can you help me with my math homework"), - tutor.message("Absolutely send me your first problem!"), - . - . - . -]) +# Adding messages from a peer will automatically add them to the session +session.add_messages( + [ + alice.message("Hey there — can you help me with my math homework?"), + tutor.message("Absolutely. Send me your first problem!"), + ] +) ``` 3. Leverage reasoning from Honcho to inform your agent's behavior @@ -73,14 +70,14 @@ session.add_messages([ ### 1. Use the chat endpoint to ask questions about your users in natural language response = alice.chat("What learning styles does the user respond to best?") -### 2. Use Get context to get most recent messages and summaries to continue a conversation -context = session.get_context(summary=True, tokens=10000) +### 2. Use session context to continue a conversation with an LLM +context = session.context(summary=True, tokens=10_000) # Convert to a format to send to OpenAI and get the next message -openai_messages = context.to_openai_messages(assistant=tutor) +openai_messages = context.to_openai(assistant=tutor) from openai import OpenAI -client = Openai() +client = OpenAI() response = client.chat.completions.create( model="gpt-4", messages=openai_messages @@ -89,8 +86,8 @@ response = client.chat.completions.create( ### 3. Search for similar messages results = alice.search("Math Homework") -### 4. Get a cached representation of a Peer for the Session -alice_representation = session.working_rep("alice") +### 4. Get a session-scoped representation of a peer +alice_representation = session.representation(alice) ``` @@ -593,7 +590,7 @@ serve the needs of any given application. #### Get Context In long-running conversations with an LLM, the context window can fill up -quickly. To address this, Honcho provides a `get_context` +quickly. To address this, Honcho provides a `context` endpoint that returns a combination of messages, conclusions, summaries from a session up to a provided token limit. @@ -607,10 +604,10 @@ There are several search endpoints that let developers query messages at the Requests can include advanced filters to further refine the results. -#### Dialectic API +#### Chat API The flagship interface for using these insights is through -the [Dialectic Endpoint](https://blog.plasticlabs.ai/archive/ARCHIVED;-Introducing-Honcho's-Dialectic-API). +the [`Chat` Endpoint](https://blog.plasticlabs.ai/archive/ARCHIVED;-Introducing-Honcho's-Dialectic-API). This is a regular API endpoint (`/peers/{peer_id}/chat`) that takes natural language requests to get data about the `Peer`. This robust design lets us use this single endpoint for all @@ -625,10 +622,10 @@ API include: - Asking Honcho for a 2nd opinion or approach about how to respond to the Peer - Getting personalized responses that incorporate long-term facts and context -#### Working Representations +#### Representations For low-latency use cases, -Honcho provides access to a `get_representation` endpoint that +Honcho provides access to a `representation` endpoint that returns a static document with insights about a `Peer` in the context of a particular session. diff --git a/docs/docs.json b/docs/docs.json index a0135eeb..04784f14 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -5,7 +5,7 @@ "redirects": [ { "source": "/", - "destination": "/v3/documentation/introduction/overview" + "destination": "/v2/documentation/introduction/overview" } ], "colors": { @@ -24,206 +24,6 @@ }, "navigation": { "versions": [ - { - "version": "v2.5.1", - "api": { - "openapi": [ - "openapi.json" - ] - }, - "tabs": [ - { - "tab": "Documentation", - "groups": [ - { - "group": "Introduction", - "pages": [ - "v2/documentation/introduction/overview", - "v2/documentation/introduction/quickstart", - "v2/documentation/introduction/vibecoding" - ] - }, - { - "group": "Core Concepts", - "pages": [ - "v2/documentation/core-concepts/architecture", - "v2/documentation/core-concepts/features/storing-data", - "v2/documentation/core-concepts/features/dialectic-endpoint", - "v2/documentation/core-concepts/features/get-context", - "v2/documentation/core-concepts/features/search", - "v2/documentation/core-concepts/features/working-rep", - "v2/documentation/core-concepts/features/streaming-response", - "v2/documentation/core-concepts/features/using-filters", - "v2/documentation/core-concepts/features/file-uploads", - "v2/documentation/core-concepts/features/queue-status", - "v2/documentation/core-concepts/features/local-vs-global", - "v2/documentation/core-concepts/configuration", - "v2/documentation/core-concepts/summarizer", - "v2/documentation/core-concepts/glossary" - ] - }, - { - "group": "Reference", - "pages": [ - "v2/documentation/reference/platform", - "v2/documentation/reference/sdk" - ] - } - ] - }, - { - "tab": "Spellbooks", - "groups": [ - { - "group": "Getting Started", - "pages": [ - "v2/guides/overview" - ] - }, - { - "group": "Migrations", - "pages": [ - "v2/migrations/from-mem0" - ] - }, - { - "group": "Integrations", - "pages": [ - "v2/integrations/crewai", - "v2/integrations/langgraph", - "v2/integrations/mcp", - "v2/integrations/n8n" - ] - }, - { - "group": "Application Interfaces", - "pages": [ - "v2/guides/discord", - "v2/guides/telegram" - ] - } - ] - }, - { - "tab": "API Reference", - "groups": [ - { - "group": "API Documentation", - "pages": [ - "v2/api-reference/introduction" - ] - }, - { - "group": "workspaces", - "pages": [ - "v2/api-reference/endpoint/workspaces/get-or-create-workspace", - "v2/api-reference/endpoint/workspaces/get-all-workspaces", - "v2/api-reference/endpoint/workspaces/update-workspace", - "v2/api-reference/endpoint/workspaces/delete-workspace", - "v2/api-reference/endpoint/workspaces/search-workspace", - "v2/api-reference/endpoint/workspaces/get-deriver-status", - "v2/api-reference/endpoint/workspaces/trigger-dream" - ] - }, - { - "group": "peers", - "pages": [ - "v2/api-reference/endpoint/peers/get-peers", - "v2/api-reference/endpoint/peers/get-or-create-peer", - "v2/api-reference/endpoint/peers/update-peer", - "v2/api-reference/endpoint/peers/get-sessions-for-peer", - "v2/api-reference/endpoint/peers/chat", - "v2/api-reference/endpoint/peers/get-working-representation", - "v2/api-reference/endpoint/peers/get-peer-card", - "v2/api-reference/endpoint/peers/set-peer-card", - "v2/api-reference/endpoint/peers/get-peer-context", - "v2/api-reference/endpoint/peers/search-peer" - ] - }, - { - "group": "sessions", - "pages": [ - "v2/api-reference/endpoint/sessions/get-or-create-session", - "v2/api-reference/endpoint/sessions/get-sessions", - "v2/api-reference/endpoint/sessions/update-session", - "v2/api-reference/endpoint/sessions/delete-session", - "v2/api-reference/endpoint/sessions/clone-session", - "v2/api-reference/endpoint/sessions/get-session-peers", - "v2/api-reference/endpoint/sessions/set-session-peers", - "v2/api-reference/endpoint/sessions/add-peers-to-session", - "v2/api-reference/endpoint/sessions/remove-peers-from-session", - "v2/api-reference/endpoint/sessions/get-peer-config", - "v2/api-reference/endpoint/sessions/set-peer-config", - "v2/api-reference/endpoint/sessions/get-session-context", - "v2/api-reference/endpoint/sessions/get-session-summaries", - "v2/api-reference/endpoint/sessions/search-session" - ] - }, - { - "group": "messages", - "pages": [ - "v2/api-reference/endpoint/messages/create-messages-for-session", - "v2/api-reference/endpoint/messages/get-messages", - "v2/api-reference/endpoint/messages/get-message", - "v2/api-reference/endpoint/messages/update-message", - "v2/api-reference/endpoint/messages/create-messages-with-file" - ] - }, - { - "group": "observations", - "pages": [ - "v2/api-reference/endpoint/observations/create-observations", - "v2/api-reference/endpoint/observations/list-observations", - "v2/api-reference/endpoint/observations/query-observations", - "v2/api-reference/endpoint/observations/delete-observation" - ] - }, - { - "group": "webhooks", - "pages": [ - "v2/api-reference/endpoint/webhooks/list-webhook-endpoints", - "v2/api-reference/endpoint/webhooks/get-or-create-webhook-endpoint", - "v2/api-reference/endpoint/webhooks/delete-webhook-endpoint", - "v2/api-reference/endpoint/webhooks/test-emit" - ] - }, - { - "group": "miscellaneous", - "pages": [ - "v2/api-reference/endpoint/keys/create-key", - "v2/api-reference/endpoint/metrics" - ] - } - ] - }, - { - "tab": "Changelog", - "groups": [ - { - "group": "Overview", - "pages": [ - "changelog/introduction", - "changelog/compatibility-guide" - ] - } - ] - }, - { - "tab": "Contributing", - "groups": [ - { - "group": "Contributing", - "pages": [ - "v2/contributing/guidelines", - "v2/contributing/self-hosting", - "v2/contributing/configuration", - "v2/contributing/license" - ] - } - ] - } - ] - }, { "version": "v3.0.0", "api": { @@ -439,6 +239,206 @@ } ] }, + { + "version": "v2.5.1", + "api": { + "openapi": [ + "openapi.json" + ] + }, + "tabs": [ + { + "tab": "Documentation", + "groups": [ + { + "group": "Introduction", + "pages": [ + "v2/documentation/introduction/overview", + "v2/documentation/introduction/quickstart", + "v2/documentation/introduction/vibecoding" + ] + }, + { + "group": "Core Concepts", + "pages": [ + "v2/documentation/core-concepts/architecture", + "v2/documentation/core-concepts/features/storing-data", + "v2/documentation/core-concepts/features/dialectic-endpoint", + "v2/documentation/core-concepts/features/get-context", + "v2/documentation/core-concepts/features/search", + "v2/documentation/core-concepts/features/working-rep", + "v2/documentation/core-concepts/features/streaming-response", + "v2/documentation/core-concepts/features/using-filters", + "v2/documentation/core-concepts/features/file-uploads", + "v2/documentation/core-concepts/features/queue-status", + "v2/documentation/core-concepts/features/local-vs-global", + "v2/documentation/core-concepts/configuration", + "v2/documentation/core-concepts/summarizer", + "v2/documentation/core-concepts/glossary" + ] + }, + { + "group": "Reference", + "pages": [ + "v2/documentation/reference/platform", + "v2/documentation/reference/sdk" + ] + } + ] + }, + { + "tab": "Spellbooks", + "groups": [ + { + "group": "Getting Started", + "pages": [ + "v2/guides/overview" + ] + }, + { + "group": "Migrations", + "pages": [ + "v2/migrations/from-mem0" + ] + }, + { + "group": "Integrations", + "pages": [ + "v2/integrations/crewai", + "v2/integrations/langgraph", + "v2/integrations/mcp", + "v2/integrations/n8n" + ] + }, + { + "group": "Application Interfaces", + "pages": [ + "v2/guides/discord", + "v2/guides/telegram" + ] + } + ] + }, + { + "tab": "API Reference", + "groups": [ + { + "group": "API Documentation", + "pages": [ + "v2/api-reference/introduction" + ] + }, + { + "group": "workspaces", + "pages": [ + "v2/api-reference/endpoint/workspaces/get-or-create-workspace", + "v2/api-reference/endpoint/workspaces/get-all-workspaces", + "v2/api-reference/endpoint/workspaces/update-workspace", + "v2/api-reference/endpoint/workspaces/delete-workspace", + "v2/api-reference/endpoint/workspaces/search-workspace", + "v2/api-reference/endpoint/workspaces/get-deriver-status", + "v2/api-reference/endpoint/workspaces/trigger-dream" + ] + }, + { + "group": "peers", + "pages": [ + "v2/api-reference/endpoint/peers/get-peers", + "v2/api-reference/endpoint/peers/get-or-create-peer", + "v2/api-reference/endpoint/peers/update-peer", + "v2/api-reference/endpoint/peers/get-sessions-for-peer", + "v2/api-reference/endpoint/peers/chat", + "v2/api-reference/endpoint/peers/get-working-representation", + "v2/api-reference/endpoint/peers/get-peer-card", + "v2/api-reference/endpoint/peers/set-peer-card", + "v2/api-reference/endpoint/peers/get-peer-context", + "v2/api-reference/endpoint/peers/search-peer" + ] + }, + { + "group": "sessions", + "pages": [ + "v2/api-reference/endpoint/sessions/get-or-create-session", + "v2/api-reference/endpoint/sessions/get-sessions", + "v2/api-reference/endpoint/sessions/update-session", + "v2/api-reference/endpoint/sessions/delete-session", + "v2/api-reference/endpoint/sessions/clone-session", + "v2/api-reference/endpoint/sessions/get-session-peers", + "v2/api-reference/endpoint/sessions/set-session-peers", + "v2/api-reference/endpoint/sessions/add-peers-to-session", + "v2/api-reference/endpoint/sessions/remove-peers-from-session", + "v2/api-reference/endpoint/sessions/get-peer-config", + "v2/api-reference/endpoint/sessions/set-peer-config", + "v2/api-reference/endpoint/sessions/get-session-context", + "v2/api-reference/endpoint/sessions/get-session-summaries", + "v2/api-reference/endpoint/sessions/search-session" + ] + }, + { + "group": "messages", + "pages": [ + "v2/api-reference/endpoint/messages/create-messages-for-session", + "v2/api-reference/endpoint/messages/get-messages", + "v2/api-reference/endpoint/messages/get-message", + "v2/api-reference/endpoint/messages/update-message", + "v2/api-reference/endpoint/messages/create-messages-with-file" + ] + }, + { + "group": "observations", + "pages": [ + "v2/api-reference/endpoint/observations/create-observations", + "v2/api-reference/endpoint/observations/list-observations", + "v2/api-reference/endpoint/observations/query-observations", + "v2/api-reference/endpoint/observations/delete-observation" + ] + }, + { + "group": "webhooks", + "pages": [ + "v2/api-reference/endpoint/webhooks/list-webhook-endpoints", + "v2/api-reference/endpoint/webhooks/get-or-create-webhook-endpoint", + "v2/api-reference/endpoint/webhooks/delete-webhook-endpoint", + "v2/api-reference/endpoint/webhooks/test-emit" + ] + }, + { + "group": "miscellaneous", + "pages": [ + "v2/api-reference/endpoint/keys/create-key", + "v2/api-reference/endpoint/metrics" + ] + } + ] + }, + { + "tab": "Changelog", + "groups": [ + { + "group": "Overview", + "pages": [ + "changelog/introduction", + "changelog/compatibility-guide" + ] + } + ] + }, + { + "tab": "Contributing", + "groups": [ + { + "group": "Contributing", + "pages": [ + "v2/contributing/guidelines", + "v2/contributing/self-hosting", + "v2/contributing/configuration", + "v2/contributing/license" + ] + } + ] + } + ] + }, { "version": "v1.1.0", "api": { diff --git a/docs/v2/documentation/core-concepts/features/get-context.mdx b/docs/v2/documentation/core-concepts/features/get-context.mdx index 566f5f1a..20f8d10f 100644 --- a/docs/v2/documentation/core-concepts/features/get-context.mdx +++ b/docs/v2/documentation/core-concepts/features/get-context.mdx @@ -139,17 +139,17 @@ context = session.get_context( ``` -### Semantic Search with Last Message +### Semantic Search -Use `last_user_message` to fetch semantically relevant observations based on the most recent message: +Use `search_query` to fetch semantically relevant observations based on a query string: ```python Python -# Get context with semantic search based on last message +# Get context with semantic search based on query context = session.get_context( tokens=2000, peer_target="user-123", - last_user_message="What are my account preferences?", + search_query="What are my account preferences?", search_top_k=10, # Number of relevant observations search_max_distance=0.8, # Max semantic distance (0.0-1.0) include_most_derived=True, # Include most recent observations @@ -159,11 +159,11 @@ context = session.get_context( ```typescript TypeScript (async () => { - // Get context with semantic search based on last message + // Get context with semantic search based on query const context = await session.getContext({ tokens: 2000, peerTarget: "user-123", - lastUserMessage: "What are my account preferences?", + searchQuery: "What are my account preferences?", searchTopK: 10, // Number of relevant observations searchMaxDistance: 0.8, // Max semantic distance (0.0-1.0) includeMostDerived: true, // Include most recent observations @@ -207,7 +207,7 @@ context = session.get_context( | `tokens` | `int` | Maximum tokens to include | | `peer_target` | `str` | Peer ID to include representation for | | `peer_perspective` | `str` | Peer ID for perspective (requires peer_target) | -| `last_user_message` | `str` | Message for semantic search (requires peer_target) | +| `search_query` | `str` | Query for semantic search (requires peer_target) | | `limit_to_session` | `bool` | Limit to session observations only | | `search_top_k` | `int` | Semantic search results to include (1-100) | | `search_max_distance` | `float` | Max semantic distance (0.0-1.0) | diff --git a/docs/v2/documentation/reference/sdk.mdx b/docs/v2/documentation/reference/sdk.mdx index 87c574e4..fbed91fd 100644 --- a/docs/v2/documentation/reference/sdk.mdx +++ b/docs/v2/documentation/reference/sdk.mdx @@ -533,7 +533,7 @@ context = session.get_context( tokens=2000, peer_target="user", peer_perspective="assistant", - last_user_message="What are my preferences?", + search_query="What are my preferences?", limit_to_session=True, search_top_k=10, search_max_distance=0.8, @@ -612,7 +612,7 @@ const richContext = await session.getContext({ tokens: 2000, peerTarget: "user", peerPerspective: "assistant", - lastUserMessage: "What are my preferences?", + searchQuery: "What are my preferences?", limitToSession: true, searchTopK: 10, searchMaxDistance: 0.8, @@ -752,7 +752,7 @@ The SessionContext object has the following structure: | `tokens` | `int` | Maximum tokens to include | | `peer_target` | `str` | Peer ID to get representation for | | `peer_perspective` | `str` | Peer ID for perspective (requires peer_target) | -| `last_user_message` | `str` | Most recent message for semantic search | +| `search_query` | `str` | Query string for semantic search | | `limit_to_session` | `bool` | Limit representation to session only | | `search_top_k` | `int` | Number of semantic search results (1-100) | | `search_max_distance` | `float` | Max semantic distance (0.0-1.0) | diff --git a/docs/v3/documentation/features/get-context.mdx b/docs/v3/documentation/features/get-context.mdx index 2e27a1e3..31c7e50f 100644 --- a/docs/v3/documentation/features/get-context.mdx +++ b/docs/v3/documentation/features/get-context.mdx @@ -143,16 +143,16 @@ context = session.get_context( ``` -### Semantic Search with Last Message +### Semantic Search -Use `last_user_message` to fetch semantically relevant conclusions based on the most recent message (requires `peer_target`): +Use `search_query` to fetch semantically relevant conclusions based on a query string (requires `peer_target`): ```python Python context = session.get_context( tokens=2000, peer_target="user-123", - last_user_message="What are my coding preferences?", + search_query="What are my coding preferences?", search_top_k=10, # Number of relevant conclusions to fetch search_max_distance=0.8, # Max semantic distance (0.0-1.0) include_most_frequent=True, # Include most frequent conclusions @@ -165,7 +165,7 @@ context = session.get_context( const context = await session.getContext({ tokens: 2000, peerTarget: "user-123", - lastUserMessage: "What are my coding preferences?", + searchQuery: "What are my coding preferences?", representationOptions: { searchTopK: 10, // Number of relevant conclusions to fetch searchMaxDistance: 0.8, // Max semantic distance (0.0-1.0) @@ -211,7 +211,7 @@ context = session.get_context( | `tokens` | `int` | Maximum tokens to include | | `peer_target` | `str` | Peer ID to include representation for | | `peer_perspective` | `str` | Peer ID for perspective (requires peer_target) | -| `last_user_message` | `str` | Message for semantic search (requires peer_target) | +| `search_query` | `str` | Query for semantic search (requires peer_target) | | `limit_to_session` | `bool` | Limit to session conclusions only | | `search_top_k` | `int` | Semantic search results to include (1-100) | | `search_max_distance` | `float` | Max semantic distance (0.0-1.0) | diff --git a/docs/v3/documentation/reference/sdk.mdx b/docs/v3/documentation/reference/sdk.mdx index a520fc0a..07922767 100644 --- a/docs/v3/documentation/reference/sdk.mdx +++ b/docs/v3/documentation/reference/sdk.mdx @@ -533,7 +533,7 @@ context = session.get_context( tokens=2000, peer_target="user", peer_perspective="assistant", - last_user_message="What are my preferences?", + search_query="What are my preferences?", limit_to_session=True, search_top_k=10, search_max_distance=0.8, @@ -612,7 +612,7 @@ const richContext = await session.getContext({ tokens: 2000, peerTarget: "user", peerPerspective: "assistant", - lastUserMessage: "What are my preferences?", + searchQuery: "What are my preferences?", limitToSession: true, searchTopK: 10, searchMaxDistance: 0.8, @@ -752,7 +752,7 @@ The SessionContext object has the following structure: | `tokens` | `int` | Maximum tokens to include | | `peer_target` | `str` | Peer ID to get representation for | | `peer_perspective` | `str` | Peer ID for perspective (requires peer_target) | -| `last_user_message` | `str` | Most recent message for semantic search | +| `search_query` | `str` or `Message` | Query string or Message object for semantic search | | `limit_to_session` | `bool` | Limit representation to session only | | `search_top_k` | `int` | Number of semantic search results (1-100) | | `search_max_distance` | `float` | Max semantic distance (0.0-1.0) | diff --git a/docs/v3/openapi.json b/docs/v3/openapi.json index 355b6b42..1c2cf5a2 100644 --- a/docs/v3/openapi.json +++ b/docs/v3/openapi.json @@ -2208,7 +2208,7 @@ "description": "Number of tokens to use for the context. Includes summary if set to true. Includes representation and peer card if they are included in the response. If not provided, the context will be exhaustive (within 100000 tokens)" }, { - "name": "last_message", + "name": "search_query", "in": "query", "required": false, "schema": { @@ -2220,10 +2220,10 @@ "type": "null" } ], - "description": "The most recent message, used to fetch semantically relevant conclusions", - "title": "Last Message" + "description": "A query string used to fetch semantically relevant conclusions", + "title": "Search Query" }, - "description": "The most recent message, used to fetch semantically relevant conclusions" + "description": "A query string used to fetch semantically relevant conclusions" }, { "name": "summary", @@ -2279,11 +2279,11 @@ "required": false, "schema": { "type": "boolean", - "description": "Only used if `last_message` is provided. Whether to limit the representation to the session (as opposed to everything known about the target peer)", + "description": "Only used if `search_query` is provided. Whether to limit the representation to the session (as opposed to everything known about the target peer)", "default": false, "title": "Limit To Session" }, - "description": "Only used if `last_message` is provided. Whether to limit the representation to the session (as opposed to everything known about the target peer)" + "description": "Only used if `search_query` is provided. Whether to limit the representation to the session (as opposed to everything known about the target peer)" }, { "name": "search_top_k", @@ -2300,10 +2300,10 @@ "type": "null" } ], - "description": "Only used if `last_message` is provided. The number of semantic-search-retrieved conclusions to include in the representation", + "description": "Only used if `search_query` is provided. The number of semantic-search-retrieved conclusions to include in the representation", "title": "Search Top K" }, - "description": "Only used if `last_message` is provided. The number of semantic-search-retrieved conclusions to include in the representation" + "description": "Only used if `search_query` is provided. The number of semantic-search-retrieved conclusions to include in the representation" }, { "name": "search_max_distance", @@ -2320,10 +2320,10 @@ "type": "null" } ], - "description": "Only used if `last_message` is provided. The maximum distance to search for semantically relevant conclusions", + "description": "Only used if `search_query` is provided. The maximum distance to search for semantically relevant conclusions", "title": "Search Max Distance" }, - "description": "Only used if `last_message` is provided. The maximum distance to search for semantically relevant conclusions" + "description": "Only used if `search_query` is provided. The maximum distance to search for semantically relevant conclusions" }, { "name": "include_most_frequent", @@ -2331,11 +2331,11 @@ "required": false, "schema": { "type": "boolean", - "description": "Only used if `last_message` is provided. Whether to include the most frequent conclusions in the representation", + "description": "Only used if `search_query` is provided. Whether to include the most frequent conclusions in the representation", "default": false, "title": "Include Most Frequent" }, - "description": "Only used if `last_message` is provided. Whether to include the most frequent conclusions in the representation" + "description": "Only used if `search_query` is provided. Whether to include the most frequent conclusions in the representation" }, { "name": "max_conclusions", @@ -2352,10 +2352,10 @@ "type": "null" } ], - "description": "Only used if `last_message` is provided. The maximum number of conclusions to include in the representation", + "description": "Only used if `search_query` is provided. The maximum number of conclusions to include in the representation", "title": "Max Conclusions" }, - "description": "Only used if `last_message` is provided. The maximum number of conclusions to include in the representation" + "description": "Only used if `search_query` is provided. The maximum number of conclusions to include in the representation" } ], "responses": { @@ -3564,23 +3564,6 @@ } } } - }, - "/metrics": { - "get": { - "summary": "Metrics", - "description": "Prometheus metrics endpoint", - "operationId": "metrics_metrics_get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {} - } - } - } - } - } } }, "components": { diff --git a/sdks/python/src/honcho/aio.py b/sdks/python/src/honcho/aio.py index 20cb488b..3f2586f0 100644 --- a/sdks/python/src/honcho/aio.py +++ b/sdks/python/src/honcho/aio.py @@ -934,9 +934,9 @@ class SessionAio(AsyncMetadataConfigMixin): None, description="A peer ID to get context for.", ), - last_user_message: str | Message | None = Field( + search_query: str | Message | None = Field( None, - description="The most recent message text (string or Message object), used to fetch semantically relevant conclusions.", + description="A query string (or Message object) used to fetch semantically relevant conclusions.", ), peer_perspective: str | None = Field( None, @@ -976,15 +976,13 @@ class SessionAio(AsyncMetadataConfigMixin): "You must provide a `peer_target` when `peer_perspective` is provided" ) - if peer_target is None and last_user_message is not None: + if peer_target is None and search_query is not None: raise ValueError( - "You must provide a `peer_target` when `last_user_message` is provided" + "You must provide a `peer_target` when `search_query` is provided" ) - last_user_message_text = ( - last_user_message.content - if isinstance(last_user_message, Message) - else last_user_message + search_query_text = ( + search_query.content if isinstance(search_query, Message) else search_query ) query: dict[str, Any] = { @@ -993,8 +991,8 @@ class SessionAio(AsyncMetadataConfigMixin): } if tokens is not None: query["tokens"] = tokens - if last_user_message_text is not None: - query["last_message"] = last_user_message_text + if search_query_text is not None: + query["search_query"] = search_query_text if peer_target is not None: query["peer_target"] = peer_target if peer_perspective is not None: diff --git a/sdks/python/src/honcho/session.py b/sdks/python/src/honcho/session.py index 6f1bb77b..8414cc60 100644 --- a/sdks/python/src/honcho/session.py +++ b/sdks/python/src/honcho/session.py @@ -517,9 +517,9 @@ class Session(SessionBase, MetadataConfigMixin): None, description="A peer ID to get context for. If given *without* `peer_perspective`, a representation and peer card will be included from the omniscient Honcho-level view of `peer_target`. If given *with* `peer_perspective`, will get the representation and card for `peer_target` *from the perspective of `peer_perspective`*.", ), - last_user_message: str | Message | None = Field( + search_query: str | Message | None = Field( None, - description="The most recent message text (string or Message object), used to fetch semantically relevant conclusions. Use this alongside `peer_target` to get a more focused context -- does nothing if `peer_target` is not provided.", + description="A query string (or Message object) used to fetch semantically relevant conclusions. Use this alongside `peer_target` to get a more focused context -- does nothing if `peer_target` is not provided.", ), peer_perspective: str | None = Field( None, @@ -533,13 +533,13 @@ class Session(SessionBase, MetadataConfigMixin): None, ge=1, le=100, - description="Number of semantically relevant facts to return when searching with `last_user_message`.", + description="Number of semantically relevant facts to return when searching with `search_query`.", ), search_max_distance: float | None = Field( None, ge=0.0, le=1.0, - description="Maximum semantic distance for search results (0.0-1.0) when searching with `last_user_message`.", + description="Maximum semantic distance for search results (0.0-1.0) when searching with `search_query`.", ), include_most_frequent: bool | None = Field( None, @@ -565,7 +565,7 @@ class Session(SessionBase, MetadataConfigMixin): tokens: Maximum number of tokens to include in the context. Will default to Honcho server configuration if not provided. peer_target: A peer ID to get context for. - last_user_message: The most recent message for semantic search. + search_query: A query string for semantic search. peer_perspective: A peer ID to get context from the perspective of. limit_to_session: Whether to limit the representation to this session only. search_top_k: Number of semantically relevant facts to return. @@ -589,15 +589,13 @@ class Session(SessionBase, MetadataConfigMixin): "You must provide a `peer_target` when `peer_perspective` is provided" ) - if peer_target is None and last_user_message is not None: + if peer_target is None and search_query is not None: raise ValueError( - "You must provide a `peer_target` when `last_user_message` is provided" + "You must provide a `peer_target` when `search_query` is provided" ) - last_user_message_text = ( - last_user_message.content - if isinstance(last_user_message, Message) - else last_user_message + search_query_text = ( + search_query.content if isinstance(search_query, Message) else search_query ) query: dict[str, Any] = { @@ -606,8 +604,8 @@ class Session(SessionBase, MetadataConfigMixin): } if tokens is not None: query["tokens"] = tokens - if last_user_message_text is not None: - query["last_message"] = last_user_message_text + if search_query_text is not None: + query["search_query"] = search_query_text if peer_target is not None: query["peer_target"] = peer_target if peer_perspective is not None: diff --git a/sdks/typescript/src/session.ts b/sdks/typescript/src/session.ts index e8f12f05..6d257f71 100644 --- a/sdks/typescript/src/session.ts +++ b/sdks/typescript/src/session.ts @@ -186,7 +186,7 @@ export class Session { private async _getContext(params: { tokens?: number summary?: boolean - last_message?: string + search_query?: string peer_target?: string peer_perspective?: string limit_to_session?: boolean @@ -699,7 +699,7 @@ export class Session { summary?: boolean tokens?: number peerTarget?: string | Peer - lastUserMessage?: string | Message + searchQuery?: string | Message peerPerspective?: string | Peer limitToSession?: boolean representationOptions?: RepresentationOptions @@ -713,30 +713,30 @@ export class Session { typeof opts.peerPerspective === 'object' ? opts.peerPerspective.id : opts.peerPerspective - const lastUserMessageText = - typeof opts.lastUserMessage === 'string' - ? opts.lastUserMessage - : opts.lastUserMessage?.content + const searchQueryText = + typeof opts.searchQuery === 'string' + ? opts.searchQuery + : opts.searchQuery?.content const contextParams = ContextParamsSchema.parse({ summary: opts.summary, tokens: opts.tokens, peerTarget: peerTargetId, - lastUserMessage: lastUserMessageText, + searchQuery: searchQueryText, peerPerspective: peerPerspectiveId, limitToSession: opts.limitToSession, representationOptions: opts.representationOptions, }) - const lastMessageText = - typeof contextParams.lastUserMessage === 'string' - ? contextParams.lastUserMessage - : contextParams.lastUserMessage?.content + const searchQueryParsed = + typeof contextParams.searchQuery === 'string' + ? contextParams.searchQuery + : contextParams.searchQuery?.content const context = await this._getContext({ tokens: contextParams.tokens, summary: contextParams.summary, - last_message: lastMessageText, + search_query: searchQueryParsed, peer_target: contextParams.peerTarget, peer_perspective: contextParams.peerPerspective, limit_to_session: contextParams.limitToSession, diff --git a/sdks/typescript/src/types/api.ts b/sdks/typescript/src/types/api.ts index 6e1a53b3..236db6e5 100644 --- a/sdks/typescript/src/types/api.ts +++ b/sdks/typescript/src/types/api.ts @@ -155,7 +155,7 @@ export interface SessionPeerConfigParams { export interface SessionContextParams { tokens?: number summary?: boolean - last_message?: string + search_query?: string peer_target?: string peer_perspective?: string limit_to_session?: boolean diff --git a/sdks/typescript/src/validation.ts b/sdks/typescript/src/validation.ts index 073f8f5c..3a5e8584 100644 --- a/sdks/typescript/src/validation.ts +++ b/sdks/typescript/src/validation.ts @@ -271,9 +271,9 @@ export const ContextParamsSchema = z .object({ summary: z.boolean().optional(), tokens: z.int('Token limit must be an integer').optional(), - lastUserMessage: z + searchQuery: z .union([ - z.string().min(1, 'Last user message must be a non-empty string'), + z.string().min(1, 'Search query must be a non-empty string'), MessageResponseSchema, ]) .optional(), @@ -283,11 +283,11 @@ export const ContextParamsSchema = z representationOptions: RepresentationOptionsSchema.optional(), }) .superRefine((data, ctx) => { - if (data.lastUserMessage && !data.peerTarget) { + if (data.searchQuery && !data.peerTarget) { ctx.addIssue({ code: z.ZodIssueCode.custom, - message: 'peerTarget is required when lastUserMessage is provided', - path: ['lastUserMessage'], + message: 'peerTarget is required when searchQuery is provided', + path: ['searchQuery'], }) } diff --git a/src/routers/sessions.py b/src/routers/sessions.py index 4e141837..7cad530e 100644 --- a/src/routers/sessions.py +++ b/src/routers/sessions.py @@ -508,9 +508,9 @@ async def get_session_context( description=f"Number of tokens to use for the context. Includes summary if set to true. Includes representation and peer card if they are included in the response. If not provided, the context will be exhaustive (within {config.settings.GET_CONTEXT_MAX_TOKENS} tokens)", ), *, - last_message: str | None = Query( + search_query: str | None = Query( None, - description="The most recent message, used to fetch semantically relevant conclusions", + description="A query string used to fetch semantically relevant conclusions", ), include_summary: bool = Query( default=True, @@ -527,29 +527,29 @@ async def get_session_context( ), limit_to_session: bool = Query( default=False, - description="Only used if `last_message` is provided. Whether to limit the representation to the session (as opposed to everything known about the target peer)", + description="Only used if `search_query` is provided. Whether to limit the representation to the session (as opposed to everything known about the target peer)", ), search_top_k: int | None = Query( None, ge=1, le=100, - description="Only used if `last_message` is provided. The number of semantic-search-retrieved conclusions to include in the representation", + description="Only used if `search_query` is provided. The number of semantic-search-retrieved conclusions to include in the representation", ), search_max_distance: float | None = Query( None, ge=0.0, le=1.0, - description="Only used if `last_message` is provided. The maximum distance to search for semantically relevant conclusions", + description="Only used if `search_query` is provided. The maximum distance to search for semantically relevant conclusions", ), include_most_frequent: bool = Query( default=False, - description="Only used if `last_message` is provided. Whether to include the most frequent conclusions in the representation", + description="Only used if `search_query` is provided. Whether to include the most frequent conclusions in the representation", ), max_conclusions: int | None = Query( None, ge=1, le=100, - description="Only used if `last_message` is provided. The maximum number of conclusions to include in the representation", + description="Only used if `search_query` is provided. The maximum number of conclusions to include in the representation", ), ): """ @@ -585,7 +585,7 @@ async def get_session_context( # with tracked_db creating separate database sessions representation = await _get_working_representation_task( workspace_id, - last_message, + search_query, observer=observer, observed=observed, session_name=session_id if limit_to_session else None, diff --git a/tests/bench/beam.py b/tests/bench/beam.py index 352106f5..3a9f3290 100644 --- a/tests/bench/beam.py +++ b/tests/bench/beam.py @@ -189,7 +189,7 @@ class BEAMRunner(RunnerMixin): context = await session.aio.context( summary=True, peer_target="user", - last_user_message=question, + search_query=question, ) context_messages = context.to_openai(assistant="assistant") context_messages.append({"role": "user", "content": question}) diff --git a/tests/bench/locomo.py b/tests/bench/locomo.py index cfa2c969..4fe3fc2b 100644 --- a/tests/bench/locomo.py +++ b/tests/bench/locomo.py @@ -415,7 +415,7 @@ class LoCoMoRunner(RunnerMixin): context = await session.aio.context( summary=True, peer_target=target_speaker, - last_user_message=question, + search_query=question, ) context_messages = context.to_anthropic(assistant="assistant") context_messages.append({"role": "user", "content": question}) diff --git a/tests/bench/longmem.py b/tests/bench/longmem.py index 8072d90f..0ed1b7f3 100644 --- a/tests/bench/longmem.py +++ b/tests/bench/longmem.py @@ -557,7 +557,7 @@ class LongMemEvalRunner(RunnerMixin): context = await session.aio.context( summary=True, peer_target=peer_id, - last_user_message=question, + search_query=question, ) # Format context using to_anthropic method diff --git a/tests/routes/test_sessions.py b/tests/routes/test_sessions.py index fe8379f8..c7025253 100644 --- a/tests/routes/test_sessions.py +++ b/tests/routes/test_sessions.py @@ -1149,10 +1149,10 @@ def test_get_session_context_peer_perspective_without_target_fails( assert "peer_target" in error_detail.lower() -def test_get_session_context_with_last_message( +def test_get_session_context_with_search_query( client: TestClient, sample_data: tuple[Workspace, Peer] ): - """Test session context with last_message parameter for semantic search""" + """Test session context with search_query parameter for semantic search""" test_workspace, test_peer = sample_data session_id = str(generate_nanoid()) @@ -1162,12 +1162,12 @@ def test_get_session_context_with_last_message( json={"id": session_id, "peers": {test_peer.name: {}}}, ) - # Get context with last_message and peer_target + # Get context with search_query and peer_target response = client.get( f"/v3/workspaces/{test_workspace.name}/sessions/{session_id}/context", params={ "peer_target": test_peer.name, - "last_message": "What is my favorite color?", + "search_query": "What is my favorite color?", }, ) assert response.status_code == 200 @@ -1193,7 +1193,7 @@ def test_get_session_context_with_limit_to_session( f"/v3/workspaces/{test_workspace.name}/sessions/{session_id}/context", params={ "peer_target": test_peer.name, - "last_message": "Test query", + "search_query": "Test query", "limit_to_session": True, }, ) @@ -1220,7 +1220,7 @@ def test_get_session_context_with_search_parameters( f"/v3/workspaces/{test_workspace.name}/sessions/{session_id}/context", params={ "peer_target": test_peer.name, - "last_message": "Test query", + "search_query": "Test query", "search_top_k": 5, "search_max_distance": 0.8, # float value (semantic distance 0.0-1.0) }, @@ -1248,7 +1248,7 @@ def test_get_session_context_with_include_most_frequent( f"/v3/workspaces/{test_workspace.name}/sessions/{session_id}/context", params={ "peer_target": test_peer.name, - "last_message": "Test query", + "search_query": "Test query", "include_most_frequent": True, }, ) @@ -1275,7 +1275,7 @@ def test_get_session_context_with_max_observations( f"/v3/workspaces/{test_workspace.name}/sessions/{session_id}/context", params={ "peer_target": test_peer.name, - "last_message": "Test query", + "search_query": "Test query", "max_observations": 10, }, ) @@ -1312,7 +1312,7 @@ def test_get_session_context_with_all_representation_params( "tokens": 500, "peer_target": test_peer.name, "peer_perspective": peer2_name, - "last_message": "What do you know about me?", + "search_query": "What do you know about me?", "limit_to_session": True, "search_top_k": 10, "search_max_distance": 0.9, # float value (semantic distance 0.0-1.0)