# Quick Start: Chat Table

{% stepper %}
{% step %}

### Introduction

This guide will help you quickly get started with JamAI Base chat tables using the TypeScript SDK. You'll learn how to create a simple chat application similar to the example provided.
{% endstep %}

{% step %}

### Prerequisites

* Node.js 16.x or higher
* JamAI Base account
* Personal Access Token (PAT)
* Project ID
  {% endstep %}

{% step %}

### Installation

```bash
npm install jamaibase
```

{% endstep %}

{% step %}

### Basic Setup

Get your Personal Access Token (PAT) here:

Get your Project ID here:

```typescript
import JamAI from "jamaibase";

// Initialize JamAI client
const jamai = new JamAI({
  projectId: "your_project_id", // Replace with your project ID
  token: "your_pat_token", // Replace with your PAT
});
```

{% endstep %}

{% step %}

### Creating a Chat Agent (UI First)

Go to JamAI Base web interface chat table tab

Navigate to "Agents" section, click **`+`** to create new agent.

Name the new agent `"example_agent"` and select LLM model.

You can further configure your agent in UI but it will not be covered in this tutorial.

Example of some configuration you can do:

* Set system prompt
* Set multiple parallel agents
* Configure RAG settings
* Set up knowledge base
  {% endstep %}

{% step %}

### Creating Chat Sessions

Each chat session is created by duplicating your base agent table. Here's how to do it:

```typescript
async function createNewChat(): Promise<string | null> {
  const timestamp = Date.now();
  const newTableId = `Chat_${timestamp}`;

  try {
    await jamai.table.duplicateTable({
      table_type: "chat",
      table_id_src: "example_agent", // Your base agent ID
      table_id_dst: newTableId,
      include_data: true,
      create_as_child: true,
    });
    return newTableId;
  } catch (error) {
    console.error(`Error creating new chat: ${error}`);
    return null;
  }
}
```

{% endstep %}

{% step %}

### Basic Chat Interaction

```typescript
// Send a message and get response
async function chatInteraction(
  tableId: string,
  userMessage: string
): Promise<string> {
  const response = await jamai.table.addRowStream({
    table_type: "chat",
    table_id: tableId,
    data: [{ User: userMessage }],
  });

  // For streaming response
  let fullResponse = "";

  for await (const value of response) {
    if (
      value.object === "gen_table.completion.chunk" &&
      value.choices?.[0]?.message?.content
    ) {
      fullResponse += value.choices[0].message.content;
      console.log(value.choices[0].message.content);
    }
  }

  return fullResponse;
}

// For non-streaming response
async function chatInteractionNonStream(tableId: string, userMessage: string) {
  const response = await jamai.table.addRow({
    table_type: "chat",
    table_id: tableId,
    data: [{ User: userMessage }],
    concurrent: false,
  });

  return response.rows[0]?.columns["AI"]?.choices[0]?.message?.content;
}
```

{% endstep %}

{% step %}

### Simple Implementation Example

```typescript
async function main() {
  // Create a new chat session
  const chatId = await createNewChat();

  if (chatId) {
    // Send a message
    const response = await chatInteraction(chatId, "Hello, how are you?");
    console.log("\nAI:", response);
  }
}

main().catch(console.error);
```

{% endstep %}

{% step %}

### Key Features

* **Streaming Responses**: Use `addRowStream()` for real-time responses
* **Session Management**: Each chat creates a new table instance
* **Inheritance**: New chats inherit settings from the base agent
* **History Preservation**: Chat history is maintained in the table
  {% endstep %}

{% step %}

### Best Practices

* Create a new chat session for each conversation
* Handle exceptions during table creation
* Store chat IDs for session management
* Clean up unused chat tables periodically
  {% endstep %}

{% step %}

### Complete Runnable Example with CLI

Here's a complete, standalone example that you can copy, paste, and run in the terminal:

```typescript
import JamAI from "jamaibase";
import * as readline from "readline";
import * as dotenv from "dotenv";

// Load environment variables (optional)
dotenv.config();

// Constants
const PROJECT_ID = process.env.JAMAI_PROJECT_ID || "your_project_id";
const PAT = process.env.JAMAI_API_KEY || "your_pat_token";
const AGENT_ID = "example_agent"; // Replace with your agent ID
const OPENER = "Hello! How can I help you today?";

// Initialize JamAI
const jamai = new JamAI({
  projectId: PROJECT_ID,
  token: PAT,
});

interface Message {
  role: "user" | "assistant";
  content: string;
}

class ChatSession {
  private tableId: string | null = null;
  private messages: Message[] = [];
  private rl: readline.Interface;

  constructor() {
    this.rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout,
    });
  }

  async initialize(): Promise<boolean> {
    this.tableId = await this.createNewChat();
    if (this.tableId) {
      this.messages.push({ role: "assistant", content: OPENER });
      console.log(`\nAssistant: ${OPENER}\n`);
      return true;
    }
    return false;
  }

  async createNewChat(): Promise<string | null> {
    const timestamp = Date.now();
    const newTableId = `Chat_${timestamp}`;

    try {
      await jamai.table.duplicateTable({
        table_type: "chat",
        table_id_src: AGENT_ID,
        table_id_dst: newTableId,
        include_data: true,
        create_as_child: true,
      });
      console.log(`Created new chat session: ${newTableId}`);
      return newTableId;
    } catch (error) {
      console.error(`Error creating new chat: ${error}`);
      return null;
    }
  }

  async sendMessage(userMessage: string): Promise<void> {
    if (!this.tableId) {
      console.error("No active chat session");
      return;
    }

    // Add user message
    this.messages.push({ role: "user", content: userMessage });

    // Get AI response with streaming
    console.log("\nAssistant: ");

    const response = await jamai.table.addRowStream({
      table_type: "chat",
      table_id: this.tableId,
      data: [{ User: userMessage }],
    });

    let fullResponse = "";

    for await (const value of response) {
      if (
        value.object === "gen_table.completion.chunk" &&
        value.choices?.[0]?.message?.content
      ) {
        const content = value.choices[0].message.content;
        fullResponse += content;
        console.log(content);
      }
    }

    console.log("\n");
    this.messages.push({ role: "assistant", content: fullResponse });
  }

  async startChat(): Promise<void> {
    console.log(
      "\nChat started! Type 'exit' to quit, 'new' to start a new chat.\n"
    );

    const askQuestion = () => {
      this.rl.question("You: ", async (input) => {
        const userInput = input.trim();

        if (userInput.toLowerCase() === "exit") {
          console.log("Goodbye!");
          this.rl.close();
          process.exit(0);
        } else if (userInput.toLowerCase() === "new") {
          const success = await this.initialize();
          if (success) {
            askQuestion();
          } else {
            console.log("Failed to create new chat. Exiting...");
            this.rl.close();
            process.exit(1);
          }
        } else if (userInput) {
          await this.sendMessage(userInput);
          askQuestion();
        } else {
          askQuestion();
        }
      });
    };

    askQuestion();
  }
}

async function main() {
  console.log("=== JamAI Base Chat Demo ===\n");

  const chat = new ChatSession();
  const initialized = await chat.initialize();

  if (initialized) {
    await chat.startChat();
  } else {
    console.error("Failed to initialize chat session");
    process.exit(1);
  }
}

main().catch(console.error);
```

How to Run:

1. Save the code in a file (e.g., `chat_demo.ts`)
2. Create a `.env` file:

   ```
   JAMAI_PROJECT_ID=your_project_id
   JAMAI_API_KEY=your_pat_token
   ```
3. Install required packages:

   ```bash
   npm install jamaibase dotenv
   npm install --save-dev @types/node typescript ts-node
   ```
4. Replace the following values in the code:
   * `AGENT_ID` with your agent ID created in the UI (or use environment variable)
5. Run the application:

   ```bash
   ts-node chat_demo.ts
   ```

Or compile and run:

```bash
tsc chat_demo.ts
node chat_demo.js
```

Using the Chat Demo:

* Type your message and press Enter to chat
* Type `new` to start a new chat session
* Type `exit` to quit the application
  {% endstep %}

{% step %}

### Web-Based Chat Example (Express + HTML)

Server (TypeScript):

```typescript
import JamAI from "jamaibase";
import express from "express";
import * as dotenv from "dotenv";

dotenv.config();

const app = express();
const PORT = 3000;

const PROJECT_ID = process.env.JAMAI_PROJECT_ID || "your_project_id";
const PAT = process.env.JAMAI_API_KEY || "your_pat_token";
const AGENT_ID = "example_agent";

const jamai = new JamAI({
  projectId: PROJECT_ID,
  token: PAT,
});

app.use(express.json());
app.use(express.static("public"));

// Create new chat session
app.post("/api/chat/new", async (req, res) => {
  try {
    const timestamp = Date.now();
    const newTableId = `Chat_${timestamp}`;

    await jamai.table.duplicateTable({
      table_type: "chat",
      table_id_src: AGENT_ID,
      table_id_dst: newTableId,
      include_data: true,
      create_as_child: true,
    });

    res.json({ chatId: newTableId });
  } catch (error) {
    res.status(500).json({ error: String(error) });
  }
});

// Send message
app.post("/api/chat/message", async (req, res) => {
  try {
    const { chatId, message } = req.body;

    const response = await jamai.table.addRow({
      table_type: "chat",
      table_id: chatId,
      data: [{ User: message }],
      concurrent: false,
    });

    const aiResponse =
      response.rows[0]?.columns["AI"]?.choices[0]?.message?.content;
    res.json({ response: aiResponse });
  } catch (error) {
    res.status(500).json({ error: String(error) });
  }
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});
```

Save the following HTML in `public/index.html`:

```html
<!DOCTYPE html>
<html>
  <head>
    <title>JamAI Chat Demo</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        max-width: 800px;
        margin: 50px auto;
      }
      #chat {
        border: 1px solid #ccc;
        height: 400px;
        overflow-y: scroll;
        padding: 10px;
        margin-bottom: 10px;
      }
      .message {
        margin: 10px 0;
        padding: 10px;
        border-radius: 5px;
      }
      .user {
        background: #e3f2fd;
        text-align: right;
      }
      .assistant {
        background: #f5f5f5;
      }
      #input {
        width: 80%;
        padding: 10px;
      }
      button {
        padding: 10px 20px;
      }
    </style>
  </head>
  <body>
    <h1>JamAI Chat Demo</h1>
    <div id="chat"></div>
    <input type="text" id="input" placeholder="Type your message..." />
    <button onclick="sendMessage()">Send</button>
    <button onclick="newChat()">New Chat</button>

    <script>
      let chatId = null;

      async function newChat() {
        const response = await fetch("/api/chat/new", { method: "POST" });
        const data = await response.json();
        chatId = data.chatId;
        document.getElementById("chat").innerHTML = "";
        addMessage("assistant", "Hello! How can I help you today?");
      }

      async function sendMessage() {
        const input = document.getElementById("input");
        const message = input.value.trim();
        if (!message || !chatId) return;

        addMessage("user", message);
        input.value = "";

        const response = await fetch("/api/chat/message", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ chatId, message }),
        });

        const data = await response.json();
        addMessage("assistant", data.response);
      }

      function addMessage(role, content) {
        const chat = document.getElementById("chat");
        const div = document.createElement("div");
        div.className = `message ${role}`;
        div.textContent = content;
        chat.appendChild(div);
        chat.scrollTop = chat.scrollHeight;
      }

      // Initialize with new chat
      newChat();
    </script>
  </body>
</html>
```

Run the server:

```bash
npm install express dotenv
ts-node server.ts
```

Then open `http://localhost:3000` in your browser.
{% endstep %}

{% step %}

### Summary

This example provides:

* A simple chat interface (CLI and Web-based)
* Streaming and non-streaming responses
* New chat session creation
* Basic error handling

Note: Make sure you have created your agent in the JamAI Base UI before running this code, as it relies on duplicating an existing agent table.

This example serves as a great starting point for building more complex chat applications with JamAI Base using TypeScript/JavaScript.
{% endstep %}
{% endstepper %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.jamaibase.com/developer-reference/typescript-sdk-documentation/quick-start-chat-table.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
