/** * March Agent SDK - Conversation Client * Port of Python march_agent/conversation_client.py */ import { APIException } from './exceptions.js' import type { ConversationData, GetMessagesOptions, ConversationMessageData } from './types.js' /** * HTTP client for interacting with conversation-store API. */ export class ConversationClient { private readonly baseUrl: string constructor(baseUrl: string) { this.baseUrl = baseUrl.replace(/\/$/, '') } /** * Get conversation metadata. */ async getConversation(conversationId: string): Promise { const url = `${this.baseUrl}/conversations/${conversationId}` try { const response = await fetch(url) if (response.status === 404) { throw new APIException(`Conversation ${conversationId} not found`, 404) } if (!response.ok) { throw new APIException(`Failed to fetch conversation: ${response.status}`, response.status) } return await response.json() as ConversationData } catch (error) { if (error instanceof APIException) throw error throw new APIException(`Failed to fetch conversation: ${error}`) } } /** * Get messages from a conversation. */ async getMessages( conversationId: string, options: GetMessagesOptions = {} ): Promise { const url = new URL(`${this.baseUrl}/conversations/${conversationId}/messages`) const params: Record = { limit: String(Math.min(options.limit ?? 100, 1000)), offset: String(options.offset ?? 0), } if (options.role) params.role = options.role if (options.from) params.from = options.from if (options.to) params.to = options.to Object.entries(params).forEach(([key, value]) => { url.searchParams.set(key, value) }) try { const response = await fetch(url.toString()) if (response.status === 404) { throw new APIException(`Conversation ${conversationId} not found`, 404) } if (!response.ok) { throw new APIException(`Failed to fetch messages: ${response.status}`, response.status) } return await response.json() as ConversationMessageData[] } catch (error) { if (error instanceof APIException) throw error throw new APIException(`Failed to fetch messages: ${error}`) } } /** * Update conversation fields (PATCH). */ async updateConversation( conversationId: string, data: Partial ): Promise { const url = `${this.baseUrl}/conversations/${conversationId}` try { const response = await fetch(url, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }) if (!response.ok) { throw new APIException(`Failed to update conversation: ${response.status}`, response.status) } return await response.json() as ConversationData } catch (error) { if (error instanceof APIException) throw error throw new APIException(`Failed to update conversation: ${error}`) } } }