/**
 * Abstract client class for interacting with the Axiom Lattice Agent Service API
 * Provides common functionality for different client implementations
 */
export class AbstractClient {
    /**
     * Creates a new AbstractClient instance
     * @param config - Configuration options for the client
     */
    constructor(config) {
        this.tenantId = "";
        this.registeredTools = new Map();
        /**
         * Chat namespace for sending messages and streaming responses
         */
        this.chat = {
            /**
             * Sends a message to a thread and receives a response
             * @param options - Options for sending a message
             * @returns A promise that resolves to the chat response
             */
            send: async (options) => {
                try {
                    // Extract the message from the messages array (assuming the last message is the one to send)
                    const message = options.messages[options.messages.length - 1];
                    const { command, threadId, files, ...rest } = options;
                    // Use the run method to send the message
                    const result = await this.run({
                        threadId: threadId,
                        message: typeof message.content === "string"
                            ? message.content
                            : JSON.stringify(message.content),
                        streaming: false,
                        command: command,
                        files: files,
                        ...rest,
                    });
                    return result;
                }
                catch (error) {
                    throw error;
                }
            },
            /**
             * Sends a message to a thread and streams the response
             * @param options - Options for streaming a message
             * @param onEvent - Callback function that receives stream events
             * @param onComplete - Optional callback function called when streaming completes
             * @param onError - Optional callback function called when an error occurs
             * @returns A function that can be called to stop the stream
             */
            stream: (options, onEvent, onComplete, onError) => {
                const { command, threadId, files, background, enableReturnStateWhenSteamCompleted, ...rest } = options;
                // Extract the message from the messages array (assuming the last message is the one to send)
                const message = options.messages[options.messages.length - 1];
                // Use the streamRequest method to stream the response
                return this.streamRequest({
                    threadId: options.threadId,
                    message: typeof message.content === "string"
                        ? message.content
                        : JSON.stringify(message.content),
                    streaming: true,
                    command: command,
                    background: background,
                    enableReturnStateWhenSteamCompleted: enableReturnStateWhenSteamCompleted,
                    ...rest,
                }, onEvent, onComplete, onError);
            },
        };
        /**
         * Tools namespace for registering and unregistering client-side tools
         */
        this.tools = {
            /**
             * Registers a client-side tool
             * @param options - Options for registering a tool
             */
            register: (options) => {
                if (this.config.transport !== "ws") {
                    throw new Error("Client-side tools are only supported with WebSocket transport");
                }
                this.registeredTools.set(options.name, options);
            },
            /**
             * Unregisters a client-side tool
             * @param name - Tool name
             */
            unregister: (name) => {
                this.registeredTools.delete(name);
            },
        };
        this.config = {
            timeout: 300000, // Default timeout
            ...config,
        };
        this.assistantId = config.assistantId;
    }
    /**
     * Abstract method for streaming API requests
     * To be implemented by concrete client classes
     */
    /**
     * Helper method to build stream request parameters
     * @param options - Options for running the agent
     * @returns The formatted request parameters
     */
    buildStreamRequestParams(options) {
        const { command, threadId, message, files, background, ...rest } = options;
        return {
            url: "/api/runs",
            method: "POST",
            body: {
                assistant_id: this.assistantId,
                thread_id: threadId,
                message: message,
                files: files,
                command: command,
                streaming: true,
                background: background || false,
                ...rest,
            },
        };
    }
    /**
     * Creates a new thread
     * @param options - Options for creating a thread
     * @returns A promise that resolves to the thread ID
     */
    async createThread(options) {
        try {
            const data = await this.makeRequest("/threads", {
                method: "POST",
                body: {
                    ...options,
                    assistantId: this.assistantId,
                },
            });
            return data.id;
        }
        catch (error) {
            throw error;
        }
    }
    /**
     * Retrieves thread information
     * @param threadId - Thread identifier
     * @returns A promise that resolves to the thread information
     */
    async getThread(threadId) {
        try {
            const url = `/threads/${threadId}?assistantId=${this.assistantId}`;
            return await this.makeRequest(url);
        }
        catch (error) {
            throw error;
        }
    }
    /**
     * Lists all threads
     * @param options - Options for listing threads
     * @returns A promise that resolves to an array of threads
     */
    async listThreads(options) {
        try {
            let url = `/threads?assistantId=${this.assistantId}`;
            if (options?.limit) {
                url += `&limit=${options.limit}`;
            }
            if (options?.offset !== undefined) {
                url += `&offset=${options.offset}`;
            }
            const data = await this.makeRequest(url);
            return data.threads;
        }
        catch (error) {
            throw error;
        }
    }
    /**
     * Deletes a thread
     * @param threadId - Thread identifier
     * @returns A promise that resolves when the thread is deleted
     */
    async deleteThread(threadId) {
        try {
            const url = `/threads/${threadId}?assistantId=${this.assistantId}`;
            await this.makeRequest(url, { method: "DELETE" });
        }
        catch (error) {
            throw error;
        }
    }
    /**
     * Retrieves messages from a thread
     * @param options - Options for retrieving messages
     * @returns A promise that resolves to an array of messages
     */
    async getMessages(options) {
        try {
            let url = `/api/assistants/${this.assistantId}/${options.threadId}/memory`;
            if (options.limit) {
                url += `?limit=${options.limit}`;
            }
            if (options.after) {
                url += url.includes("?")
                    ? `&after=${options.after}`
                    : `?after=${options.after}`;
            }
            if (options.reverse !== undefined) {
                url += url.includes("?")
                    ? `&reverse=${options.reverse}`
                    : `?reverse=${options.reverse}`;
            }
            url += url.includes("?")
                ? `&assistantId=${this.assistantId}`
                : `?assistantId=${this.assistantId}`;
            return await this.makeRequest(url);
        }
        catch (error) {
            throw error;
        }
    }
    /**
     * Retrieves agent state
     * @param threadId - Thread identifier
     * @returns A promise that resolves to the agent state
     */
    async getAgentState(threadId) {
        try {
            return await this.makeRequest(`/api/assistants/${this.assistantId}/${threadId}/state`);
        }
        catch (error) {
            throw error;
        }
    }
    /**
     * Gets agent graph visualization
     * @returns A promise that resolves to the graph visualization data
     */
    async getAgentGraph() {
        try {
            const data = await this.makeRequest(`/api/assistants/${this.assistantId}/graph`);
            return data.image;
        }
        catch (error) {
            throw error;
        }
    }
    /**
     * Run agent with options
     * @param options - Options for running the agent
     * @returns A promise that resolves to the run result
     */
    async run(options) {
        try {
            const { command, threadId, message, files, background, ...rest } = options;
            if (options.streaming) {
                throw new Error("Streaming without callbacks is not supported. Use chat.stream with callbacks instead.");
            }
            else {
                return await this.makeRequest("/api/runs", {
                    method: "POST",
                    body: {
                        assistant_id: this.assistantId,
                        thread_id: threadId,
                        message: message,
                        files: files,
                        command: command,
                        streaming: false,
                        background: background || false,
                        ...rest,
                    },
                });
            }
        }
        catch (error) {
            throw error;
        }
    }
}
//# sourceMappingURL=abstract-client.js.map