## File: README.md

# ACI: Open-Source Infra to Power Unified MCP Servers and VibeOps





> [!NOTE]
> This repo is for the ACI.dev platform. If you're looking for the **Unified MCP** server built with ACI.dev, see [aci-mcp](https://github.com/aipotheosis-labs/aci-mcp).

ACI.dev is the open-source tool-calling platform that hooks up 600+ tools into any agentic IDE or custom AI agent. It gives agents intent-aware access to tools with multi-tenant auth, granular permissions, and dynamic tool discovery—exposed as either direct function calls or through a **Unified Model-Context-Protocol (MCP) server**.

**Examples:** Instead of writing separate OAuth flows and API clients for Google Calendar, Slack, and more, use ACI.dev to manage authentication and provide AI agents with unified, secure function calls. Access these capabilities through our **Unified** [MCP server](https://github.com/aipotheosis-labs/aci-mcp) or via our lightweight [Python SDK](https://github.com/aipotheosis-labs/aci-python-sdk), compatible with any LLM framework.

Supercharge vibe coding and automate devOps by adding a single unified MCP server to your favourite agentic IDE. Configure the MCP with Vercel, Supabase, Cloudflare, and other platforms. Let AI handle provisioning, deployment, database configs, and debugging to turn a vibe coded prototype into a live product.





## 📺 Demo Video

[ACI.dev **Unified MCP Server** Demo](https://youtu.be/GSR9P53-_7E?feature=shared)

[](https://youtu.be/GSR9P53-_7E?feature=shared)

[ACI.dev **VibeOps** Demo](https://youtu.be/SfEtNqB6yqI?feature=shared)

[](https://youtu.be/SfEtNqB6yqI?feature=shared)

## ✨ Key Features

- **600+ Pre-built Integrations**: Connect to popular services and apps in minutes.
- **Flexible Access Methods**: Use our unified MCP server or our lightweight SDK for direct function calling.
- **Multi-tenant Authentication**: Built-in OAuth flows and secrets management for both developers and end-users.
- **Enhanced Agent Reliability**: Natural language permission boundaries and dynamic tool discovery.
- **Framework & Model Agnostic**: Works with any LLM framework and agent architecture.
- **100% Open Source**: Everything released under Apache 2.0 (backend, dev portal, integrations).

## 💡 Why Use ACI.dev?

ACI.dev improves tool-calling reliability and accountability:

- **Authentication at Scale**: Connect multiple users to multiple services securely.
- **Discovery Without Overload**: Find and use the right tools without overwhelming LLM context windows.
- **Natural Language Permissions**: Control agent capabilities with human-readable boundaries.
- **Tool-use Logging**: See how your agent called tools and the issues it ran into.
- **Build Once, Run Anywhere**: No vendor lock-in with our open source, framework-agnostic approach.

## 🧰 Common Use Cases

- **VibeOps:** Automate devOps by letting your agentic IDE access Vercel, Supabase, Cloudflare, Sentry and more to ship live products.
- **Personal Assistant Chatbots:** Build chatbots that can search the web, manage calendars, send emails, interact with SaaS tools, etc.
- **Research Agent:** Conducts research on specific topics and syncs results to other apps (e.g., Notion, Google Sheets).
- **Outbound Sales Agent:** Automates lead generation, email outreach, and CRM updates.
- **Customer Support Agent:** Provides answers, manages tickets, and performs actions based on customer queries.

## 🔗 Quick Links

- **Managed Service:** [aci.dev](https://www.aci.dev/)
- **Documentation:** [aci.dev/docs](https://www.aci.dev/docs)
- **Available Tools List:** [aci.dev/tools](https://www.aci.dev/tools)
- **Python SDK:** [github.com/aipotheosis-labs/aci-python-sdk](https://github.com/aipotheosis-labs/aci-python-sdk)
- **Typescript SDK:** [github.com/aipotheosis-labs/aci-typescript-sdk](https://github.com/aipotheosis-labs/aci-typescript-sdk)
- **Unified MCP Server:** [github.com/aipotheosis-labs/aci-mcp](https://github.com/aipotheosis-labs/aci-mcp)
- **Agent Examples Built with ACI.dev:** [github.com/aipotheosis-labs/aci-agents](https://github.com/aipotheosis-labs/aci-agents)
- **Blog:** [aci.dev/blog](https://www.aci.dev/blog)
- **Community:** [Discord](https://discord.com/invite/UU2XAnfHJh) | [Twitter/X](https://x.com/AipoLabs) | [LinkedIn](https://www.linkedin.com/company/aci-dev-by-aipolabs/posts/?feedView=all)

## 💻 Getting Started: Local Development

To run the full ACI.dev platform (backend server and frontend portal) locally, follow the individual README files for each component:

- **Backend:** [backend/README.md](backend/README.md)
- **Frontend:** [frontend/README.md](frontend/README.md)

## 👋 Contributing

We welcome contributions! Please see our [CONTRIBUTING.md](CONTRIBUTING.md) for more information.

## Integration Requests

Missing any integrations (apps or functions) you need? Please see our [Integration Request Template](.github/ISSUE_TEMPLATE/integration_request.yml) and submit an integration request! Or, if you're feeling adventurous, you can submit a PR to add the integration yourself!

## Star History

[](https://www.star-history.com/#aipotheosis-labs/aci&Date)

---

## File: backend/deployment/README.md

# Welcome to your CDK Python project!

This is a blank project for CDK development with Python.

The `cdk.json` file tells the CDK Toolkit how to execute your app.

This project is set up like a standard Python project.  The initialization
process also creates a virtualenv within this project, stored under the `.venv`
directory.  To create the virtualenv it assumes that there is a `python3`
(or `python` for Windows) executable in your path with access to the `venv`
package. If for any reason the automatic creation of the virtualenv fails,
you can create the virtualenv manually.

To manually create a virtualenv on MacOS and Linux:

```
$ python3 -m venv .venv
```

After the init process completes and the virtualenv is created, you can use the following
step to activate your virtualenv.

```
$ source .venv/bin/activate
```

If you are a Windows platform, you would activate the virtualenv like this:

```
% .venv\Scripts\activate.bat
```

Once the virtualenv is activated, you can install the required dependencies.

```
$ pip install -r requirements.txt
```

At this point you can now synthesize the CloudFormation template for this code.

```
$ cdk synth
```

To add additional dependencies, for example other CDK libraries, just add
them to your `setup.py` file and rerun the `pip install -r requirements.txt`
command.

## Useful commands

 * `cdk ls`          list all stacks in the app
 * `cdk synth`       emits the synthesized CloudFormation template
 * `cdk deploy`      deploy this stack to your default AWS account/region
 * `cdk diff`        compare deployed stack with current state
 * `cdk docs`        open CDK documentation

Enjoy!

---

## File: backend/README.md

# ACI.dev Backend

[](https://github.com/aipotheosis-labs/aci/actions/workflows/backend.yml)
[](https://opensource.org/licenses/Apache-2.0)

## Overview

The backend component of ACI.dev provides the server infrastructure, API endpoints, database models, and integration libraries that enable over 600+ tool integrations with multi-tenant authentication and granular permissions.

- [ACI.dev Backend](#acidev-backend)
  - [Overview](#overview)
  - [Code Structure](#code-structure)
  - [Development Setup](#development-setup)
    - [Prerequisites](#prerequisites)
    - [Code Style](#code-style)
    - [IDE Configuration](#ide-configuration)
    - [Getting Started](#getting-started)
    - [Running Tests](#running-tests)
  - [Database Management](#database-management)
    - [Working with Migrations](#working-with-migrations)
  - [PropelAuth Configuration](#propelauth-configuration)
  - [Stripe Webhooks](#stripe-webhooks)
  - [Admin CLI](#admin-cli)
  - [Running Evaluations](#running-evaluations)
  - [Contributing](#contributing)
  - [License](#license)

## Code Structure

The backend consists of several main components:

- **Server**: FastAPI application handling API requests, authentication, and tool executions
- **Database**: PostgreSQL with pgvector for vector similarity search
- **CLI**: Command-line interface for local testing and development
- **Common**: Shared code and utilities used across components

## Development Setup

### Prerequisites

- Python 3.12+
- Docker and Docker Compose
- `uv` package manager

### Code Style

We follow strict code quality standards:

- **Formatting & Linting**: We use `ruff` for code formatting and linting
- **Type Checking**: We use `mypy` for static type checking
- **Pre-commit Hooks**: Install with `pre-commit install`

### IDE Configuration

For VS Code users, configure Ruff formatter:

```json
{
    "[python]": {
      "editor.formatOnSave": true,
      "editor.defaultFormatter": "charliermarsh.ruff",
      "editor.codeActionsOnSave": {
        "source.organizeImports.ruff": "always"
      }
    }
}
```

### Getting Started

1. Clone the repository:

   ```bash
   git clone https://github.com/aipotheosis-labs/aci.git
   cd aci/backend
   ```

1. Install dependencies and activate virtual environment:

   ```bash
   uv sync
   source .venv/bin/activate
   ```

1. Install `pre-commit` hooks:

   ```bash
   pre-commit install
   ```

1. Set up environment variables for **local** development:

   ```bash
   cp .env.example .env.local
   ```

   Most sensitive variables and dummy values are already defined in `.env.example`, so you only need to set the following env vars in `.env.local`:

   - `SERVER_OPENAI_API_KEY`: Use your own OpenAI API key
   - `CLI_OPENAI_API_KEY`: Use your own OpenAI API key (can be the same as `SERVER_OPENAI_API_KEY`)

1. Start services with Docker Compose:

   ```bash
   docker compose up --build
   ```

   This will start:
   - `server`: Backend API service
   - `db`: PostgreSQL database
   - `aws`: LocalStack for mocking AWS services
   - `runner`: Container for running commands like pytest, cli commands or scripts

1. Seed the database with sample data:

   ```bash
   docker compose exec runner ./scripts/seed_db.sh
   ```

   The script will seed the database with below dummy data for local end-to-end development.
   - A default project and agent (with an API key)
   - Sample Apps and their functions
     - `Brave Search`
     - `Hacker News`
     - `Gmail` (with dummy OAuth2 credentials)

   The script will output an API key like below that you can use on the swagger UI, SDK, or
   sending HTTP requests to the local backend server directly.

   ```
   {
      'Project Id': '65cf26b9-a919-4008-85de-ecb850c3fc36',
      'Agent Id': '74273ac1-f68e-4314-b8be-fee4a5855d8a',
      'API Key': '88c55e31e817bd2d48aa455e94b61e766fb6e6610c97abe6f724733bf222e3e0'
   }
   ```

   > [!NOTE]
   > If you want to seed the database with all available apps, run the script with the `--all` flag.
   > But you'll have to manually create a secrets file `.app.secrets.json`
   > for each app that has OAuth2 scheme and put the OAuth2 credentials in that file, and the
   > insertion process might take a while.
   > See the example secrets file below for the `GMAIL` app.

   > Alternatively, you can use the `--all --mock` flags together to seed all apps with mock OAuth2 credentials.
   > This is useful for development and testing when you don't need real OAuth2 authentication.
   > The mock values will be used instead of requiring `.app.secrets.json` files.

   ```bash
   # put this in a file called .app.secrets.json under ./apps/gmail/
   {
      "AIPOLABS_GMAIL_CLIENT_ID": "<your_google_oauth2_client_id>",
      "AIPOLABS_GMAIL_CLIENT_SECRET": "<your_google_oauth2_client_secret>"
   }
   ```

1. (Optional) If you want to seed the database with specific `Apps` and `Functions`, use the cli command directly.
   > [!NOTE]
   > Add the `--skip-dry-run` flag to the commands below to actually insert the data into the database.

   ```bash
   # create app (--secrets-file is only needed for apps that have OAuth2 scheme)
   docker compose exec runner python -m aci.cli upsert-app --app-file ./apps/gmail/app.json --secrets-file ./apps/gmail/.app.secrets.json
   # create functions
   docker compose exec runner python -m aci.cli upsert-functions --functions-file ./apps/gmail/functions.json
   ```

1. (Optional) Connect to the database using a GUI client (e.g., `DBeaver`)

   - Parameters for the db connection can be found in the `.env.local` file you created in step 4.

1. Access the API documentation at:

   ```bash
   http://localhost:8000/v1/notforhuman-docs
   ```

1. (Optional) If you are developing the dev portal, follow the instructions on [frontend README](../frontend/README.md) to start the dev portal.

1. (Optional) If you are developing Stripe related billing features, follow the
    [Stripe Webhooks](#stripe-webhooks) section.

### Running Tests

```bash
docker compose exec test-runner pytest
```

## Database Management

### Working with Migrations

When making changes to database models:

1. Check for detected changes:

   ```bash
   docker compose exec runner alembic check
   ```

2. Generate a migration:

   ```bash
   docker compose exec runner alembic revision --autogenerate -m "description of changes"
   ```

3. Manually review and edit the generated file in `database/alembic/versions/` if needed to add custom changes, e.g.,:
   - pgvector library imports
   - Index creation/deletion
   - Vector extension setup
   - Other database-specific operations

4. Apply the migration (to the local db):

   ```bash
   docker compose exec runner alembic upgrade head
   ```

5. To revert the latest migration:

   ```bash
   docker compose exec runner alembic downgrade -1
   ```

## PropelAuth Configuration

> [!NOTE]
> This section is only required if you need to develop features that integrate with PropelAuth.

When developing the dev portal, you'll need an actual user and organization in PropelAuth's test environment, along with a default project and agent in your local database. This section guides you through setting up these connections.

### Values to be filled

You would need to replace a few dummy values with real values in `.env.local`:
- `SERVER_PROPELAUTH_AUTH_URL` - The authentication URL from PropelAuth
- `SERVER_PROPELAUTH_API_KEY` - Your PropelAuth API key
- `SERVER_SVIX_SIGNING_SECRET` - The signing secret for webhooks

### Setup Steps

Follow these steps to configure PropelAuth for local development:

#### 1. Set Up Ngrok

Ngrok creates a public URL for your local server, allowing PropelAuth webhooks to reach your machine:

- Install ngrok from the [getting started guide](https://ngrok.com/docs/getting-started/?os=macos)
- Start a tunnel to your local server:
  ```bash
  ngrok http http://localhost:8000
  ```
- Copy the generated public endpoint (e.g., `https://7c4c-2a06-5904-1e06-6a00-ddc6-68ce-ffae-8783.ngrok-free.app`)
- Optional: View traffic logs in the [ngrok dashboard](https://dashboard.ngrok.com/endpoints)

#### 2. Configure PropelAuth Settings

- Navigate to the [PropelAuth dashboard](https://app.propelauth.com/proj/1b327933-ffbf-4a36-bd05-76cd896b0d56)
- If needed, switch to the `aipolabs local` organization by clicking your account name and selecting **Switch to aipolabs local**

  

- In the **Users** and **Organizations** tabs:
  - Remove any previously created test users and organizations

- In the **Frontend Integrations** tab:
  - Locate and copy the Auth URL
  - Use this URL for both:
    - `SERVER_PROPELAUTH_AUTH_URL` in backend's `.env.local`
    - `NEXT_PUBLIC_AUTH_URL` in frontend's `.env`

- In the **Backend Integration** tab (if you need a new API key):
  1. Click **Create New API Key**
  2. Name it `<Your name> Local Testing`
  3. Copy the key and set it as `SERVER_PROPELAUTH_API_KEY` in `.env.local`

#### 3. Set Up Webhooks

- Navigate to **Integrations** → **Webhooks** in the dashboard
- Click **Set Up Webhooks** for the **TEST ENV**
- On the Svix endpoints page:
  1. Click **Add Endpoint**
  2. For the endpoint URL, enter your ngrok URL followed by the path:
     ```
     <your-ngrok-url>/v1/webhooks/auth/user-created
     ```
  3. Subscribe to the `user.created` event
  4. Click **Create**
- After creation:
  - Find and copy the **Signing Secret**
  - Set it as `SERVER_SVIX_SIGNING_SECRET` in `.env.local`

#### 4. Update Docker Configuration

- Edit `backend/compose.yml` to comment out the PropelAuth mock service:
  - In the `server` service section, comment out:
    ```yaml
    # - ./mock/propelauth_fastapi_mock.py:/workdir/.venv/lib/python3.12/site-packages/propelauth_fastapi/__init__.py
    ```
  - In the `runner` service section, comment out:
    ```yaml
    # - ./mock/propelauth_fastapi_mock.py:/workdir/.venv/lib/python3.12/site-packages/propelauth_fastapi/__init__.py
    ```

#### 5. Restart the Docker container

#### 6. Verify Your Setup

Test your configuration by:
- Visiting your frontend application (typically at `http://localhost:3000`)
- Creating a new account or logging in
- When successful, the webhook should trigger and automatically create the organization and project

## Stripe Webhooks

> [!NOTE]
> This is only needed if you need to develop the stripe billing features.

1. Download the [Stripe CLI](https://docs.stripe.com/stripe-cli#install)

2. Log into our Stripe Sandbox with the CLI

   ```shell
   stripe login
   ```

3. Set up webhooks with the Stripe CLI and get the webhook signing secret. By default,
all events in the Sandbox will be forwarded to the local webhook endpoint. You can also
use `--event` flag to filter the set of events you want to listen to.

   ```shell
   stripe listen --forward-to localhost:8000/v1/billing/webhook
   > Ready! You are using Stripe API Version [2025-02-24.acacia]. Your webhook signing secret is whsec_3b397734bb0362eac34a9611cc842f4a8cfb8f0e38eccf7ee666b09ac3aeec52
   ```

4. Set the following two env vars in `.env.local`:

   - `SERVER_STRIPE_SECRET_KEY`: get it from the [Stripe dashboard](https://support.stripe.com/questions/what-are-stripe-api-keys-and-how-to-find-them)
   - `SERVER_STRIPE_WEBHOOK_SIGNING_SECRET`: get it from the output of the `stripe
     listen` command you just executed

## Admin CLI

The CLI module is an internal admin tool for ACI to manage apps, functions, users, etc.
For local development, the commands can be executed via the `runner` container.

To see all available commands and their usage, run:

```bash
docker compose exec runner python -m aci.cli --help
```

Example output:

```bash
Usage: python -m aci.cli [OPTIONS] COMMAND [ARGS]...

  AIPO CLI Tool

Options:
  -h, --help  Show this message and exit.

Commands:
  create-agent                   Create an agent in db.
  create-project                 Create a project in db.
  create-random-api-key          Create a random test api key for local...
  delete-app                     Delete an app and all its references...
  fuzzy-test-function-execution  Test function execution with...
  get-app                        Get an app by name from the database.
  rename-app                     Rename an app and update all related...
  update-agent                   Update an existing agent in db.
  upsert-app                     Insert or update an App in the DB from a...
  upsert-functions               Upsert functions in the DB from a JSON...
```

To create a new app, run:

```bash
docker compose exec runner python -m aci.cli create-app --app-file ./apps/brave_search/app.json --secrets-file ./apps/brave_search/.app.secrets.json
```

## Running Evaluations

You will need to set up the following environment variables:

```bash
EVALS_SERVER_URL=<your_server_url_typically_http://localhost:8000>
EVALS_ACI_API_KEY=<your_api_key_for_the_server_returned_from_seed_db_script>
EVALS_OPENAI_KEY=<your_openai_api_key>
EVALS_WANDB_KEY=<your_wandb_api_key>
```

The evaluation results will be logged to [Weights & Biases](https://wandb.ai/aipotheosis-labs/function-search-evaluation) where you can track metrics, view experiment configurations, and analyze the results.

Then, seed the database with all apps and mock credentials:

```bash
docker compose exec runner ./scripts/seed_db.sh --all --mock
```

### Running the Evaluation Pipeline

To run the complete evaluation pipeline with different modes:

```bash
# Generate synthetic intents and evaluate them
docker compose exec runner python -m evals.evaluation_pipeline --mode generate-and-evaluate

# Only generate synthetic intent data
docker compose exec runner python -m evals.evaluation_pipeline --mode generate-only

# Only evaluate using existing dataset
docker compose exec runner python -m evals.evaluation_pipeline --mode evaluate-only
```

Additional flags:

```bash
# Specify a custom dataset artifact name (default: "synthetic_intent_dataset")
docker compose exec runner python -m evals.evaluation_pipeline --mode evaluate-only --dataset-artifact my_custom_artifact

# Specify the filename saved on the dataset artifact
docker compose exec runner python -m evals.evaluation_pipeline --mode evaluate-only --dataset-filename my_custom_dataset.csv

# Limit the number of samples to generate
docker compose exec runner python -m evals.evaluation_pipeline --mode generate-only --generation-limit 50

# Limit the number of samples to evaluate
docker compose exec runner python -m evals.evaluation_pipeline --mode evaluate-only --evaluation-samples 25
```

> [!NOTE]
> If you use the `generate-and-evaluate` mode, the pipeline will use the freshly generated dataset directly
> without having to reload it from Weights & Biases, which is more efficient.

## Contributing

Please refer to the [Contributing Guide](../CONTRIBUTING.md) for details on making contributions to this project.

## License

This project is licensed under the Apache License 2.0 - see the [LICENSE](../LICENSE) file for details.

---

## File: frontend/src/components/ui-extensions/enhanced-data-table/README.md

# EnhancedDataTable Component Documentation

The EnhancedDataTable is a data table component built on TanStack Table (React Table), providing advanced features such as sorting, filtering, searching, and row selection. This documentation will help you quickly understand and effectively use this component.

## Table of Contents

- [Basic Usage](#basic-usage)
- [Column Definitions](#column-definitions)
- [Search and Filtering](#search-and-filtering)
- [Sorting Functionality](#sorting-functionality)
- [Row Selection](#row-selection)
- [Custom Column Styling and Actions](#custom-column-styling-and-actions)
- [Practical Application Examples](#practical-application-examples)

## Basic Usage

To use the EnhancedDataTable, you need to provide two basic parameters: `columns` (column definitions) and `data` (data source).

```tsx
import { EnhancedDataTable } from "@/components/ui-extensions/enhanced-data-table/data-table";
import { useMyTableColumns } from "./useMyTableColumns";

export function MyTable({ data }) {
  // Use custom hook to get column definitions
  const columns = useMyTableColumns();

  return (
    <EnhancedDataTable
      columns={columns}
      data={data}
      searchBarProps={{ placeholder: "Search..." }}
    />
  );
}
```

## Column Definitions

It's recommended to create column definition hooks in separate files using `createColumnHelper` to get better type support.

### Creating Basic Column Definition Files

```tsx
// useMyTableColumns.tsx
import { useMemo } from "react";
import { createColumnHelper, type ColumnDef } from "@tanstack/react-table";
import { MyDataType } from "@/lib/types/myDataType";

const columnHelper = createColumnHelper<MyDataType>();

export const useMyTableColumns = (): ColumnDef<MyDataType>[] => {
  return useMemo(
    () => [
      columnHelper.accessor("name", {
        header: "Name",
        cell: (info) => info.getValue(),
        enableGlobalFilter: true,
      }),
      columnHelper.accessor("description", {
        header: "Description",
        cell: (info) => info.getValue(),
        enableGlobalFilter: true,
      }),
    ],
    [],
  );
};
```

### Column Properties Explained

- `header`: Column title, can be a string or React component
- `cell`: Cell rendering function
- `enableGlobalFilter`: Whether to include this column in global search
- `enableColumnFilter`: Whether to enable column filtering
- `filterFn`: Filter function type, e.g., "arrIncludes" for array fields
- `id`: Custom column ID, required when using accessor function
- `meta`: Used to set default sorting and other metadata

### Creating Sortable Columns

```tsx
columnHelper.accessor("name", {
  header: ({ column }) => (
     column.toggleSorting(column.getIsSorted() === "asc")}
      className="w-full justify-start px-0"
    >
      Name
      <ArrowUpDown className="h-4 w-4" />
    
  ),
  cell: (info) => info.getValue(),
  enableGlobalFilter: true,
  // Set as default sort column
  meta: {
    defaultSort: true,
    defaultSortDesc: false,
  },
});
```

## Search and Filtering

### Enabling Global Search

Provide the `searchBarProps` parameter and ensure relevant columns have `enableGlobalFilter: true`:

```tsx
<EnhancedDataTable
  columns={columns}
  data={data}
  searchBarProps={{ placeholder: "Search..." }}
/>
```

### Column Filtering Functionality

EnhancedDataTable provides single‑value dropdown filtering for array‑type columns. :

1. Set `enableColumnFilter: true`
2. Set `filterFn: "arrIncludes"`

#### Enabling Dropdown Filtering for Array Type Columns

```tsx
// Using dropdown filtering for tag arrays
columnHelper.accessor("tags", {
  header: "Tags",
  cell: (info) => (
    
      {info.getValue().map((tag) => (
        
          {tag}
        
      ))}
    
  ),
  enableGlobalFilter: true,
  enableColumnFilter: true, // Enable column filtering
  filterFn: "arrIncludes", // Specify array filtering function
});
```

#### Handling Arrays from Non-Standard Data Sources

For array data not in default fields, you can use custom accessors:

```tsx
// Handling nested objects or transforming data
columnHelper.accessor(
  (row) => row.metadata?.categories || [], // Extract array from nested object
  {
    id: "categoriesDisplay", // Must provide unique ID
    header: "Categories",
    cell: (info) => (
      
        {info.getValue().map((category) => (
          
            {category}
          
        ))}
      
    ),
    enableColumnFilter: true,
    filterFn: "arrIncludes",
  },
);
```

#### Automatic Filter UI Generation

When the following conditions are met, the table will automatically generate dropdown filter menus for columns:

1. Column has `enableColumnFilter: true`
2. Column uses `filterFn: "arrIncludes"`

Filters will be displayed in the top toolbar of the table, allowing users to select multiple values for filtering.

## Sorting Functionality

### Setting Default Sorting

You can set default sorting in two ways:

1. Using the `meta` property in column definition:

```tsx
columnHelper.accessor("createdAt", {
  header: "Created At",
  cell: (info) => new Date(info.getValue()).toLocaleString(),
  id: "createdAt",
  meta: {
    defaultSort: true,
    defaultSortDesc: true, // Default descending order
  },
});
```

2. Through the component's `defaultSorting` property:

```tsx
<EnhancedDataTable
  columns={columns}
  data={data}
  defaultSorting={[
    {
      id: "createdAt",
      desc: true,
    },
  ]}
/>
```

## Row Selection

To enable row selection functionality, you need to provide `rowSelectionProps`:

```tsx
const [rowSelection, setRowSelection] = useState({});

<EnhancedDataTable
  columns={columns}
  data={data}
  rowSelectionProps={{
    rowSelection,
    onRowSelectionChange: setRowSelection,
    getRowId: (row) => row.id,
  }}
/>;
```

This will add a selection checkbox column to the left of the table, allowing users to select multiple rows of data.

## Custom Column Styling and Actions

### Image and Text Combination Column

```tsx
columnHelper.accessor("app_name", {
  header: "App Name",
  cell: (info) => {
    const appName = info.getValue();
    return (
      
        
          {appsMap[appName]?.logo && (
            
          )}
        
        
      
    );
  },
  enableGlobalFilter: true,
});
```

### Tag Rendering

```tsx
columnHelper.accessor("tags", {
  header: "Tags",
  cell: (info) => (
    
      {(info.getValue() || []).map((tag) => (
        
          {tag}
        
      ))}
    
  ),
  enableGlobalFilter: true,
  enableColumnFilter: true,
  filterFn: "arrIncludes",
});
```

### Custom Action Buttons Column

```tsx
columnHelper.accessor(
  (row) => row, // Get entire row data
  {
    id: "actions",
    header: "",
    cell: (info) => {
      const item = info.getValue();
      return (
        
          <Link href={`/items/${item.id}`}>
            
              Open
            
          </Link>
          
            <GoTrash />
          
        
      );
    },
    enableGlobalFilter: false,
  },
);
```

### Editable Cells

```tsx
columnHelper.accessor("name", {
  header: "Name",
  cell: (ctx) => {
    const item = ctx.row.original;
    return (
      <EditableCell
        initialValue={item.name}
        fieldName="name"
        itemId={item.id}
        onUpdate={handleUpdate}
      />
    );
  },
  enableGlobalFilter: true,
});
```

## Pagination

EnhancedDataTable supports client-side pagination using TanStack Table’s built-in `getPaginationRowModel()`.

To enable pagination, pass the `paginationOptions` prop:

```tsx
<EnhancedDataTable
  columns={columns}
  data={data}
  paginationOptions={{
    initialPageIndex: 0, // Default to first page (0-based)
    initialPageSize: 10, // Number of entries per page
  }}
/>
```

## Practical Application Examples

### App Configuration Table (with Icons, Category Filtering, and Toggle Switch)

```tsx
// In page component
import { EnhancedDataTable } from "@/components/ui-extensions/enhanced-data-table/data-table";
import { useAppConfigsTableColumns } from "./useAppConfigsTableColumns";

export function AppConfigsPage() {
  const [appConfigs, setAppConfigs] = useState<AppConfig[]>([]);
  // ...other states and logic

  const appConfigsColumns = useAppConfigsTableColumns({
    linkedAccountsCountMap,
    appsMap,
    updateAppConfigs: loadAllData,
  });

  return (
    
      <EnhancedDataTable
        data={appConfigs}
        columns={appConfigsColumns}
        searchBarProps={{ placeholder: "Search apps..." }}
      />
    
  );
}
```

### Agents Table (with Editable Cells and Custom Actions)

```tsx
// In page component
import { EnhancedDataTable } from "@/components/ui-extensions/enhanced-data-table/data-table";
import { useAgentsTableColumns } from "./useAgentsTableColumns";

export function AgentsPage() {
  const [agents, setAgents] = useState<Agent[]>([]);
  // ...other states and logic

  const columns = useAgentsTableColumns(
    projectId,
    handleDeleteAgent,
    reloadAgents,
    handleInstructionsSave,
  );

  return (
    
      <EnhancedDataTable
        data={agents}
        columns={columns}
        searchBarProps={{ placeholder: "Search agents..." }}
      />
    
  );
}
```

---

## File: frontend/README.md

# Aipolabs Developer Portal


[](https://opensource.org/licenses/Apache-2.0)

The [developer portal](https://platform.aci.dev/) for Aipolabs, a platform for developers to manage and configure the apps and functions used by their agents.

## Table of Contents

- [Aipolabs Developer Portal](#aipolabs-developer-portal)
  - [Table of Contents](#table-of-contents)
  - [Description](#description)
  - [Development Setup](#development-setup)
  - [Linting \& Testing](#linting--testing)
  - [Directory Structure](#directory-structure)
  - [Conventions](#conventions)
  - [Deployment](#deployment)

## Description

The Dev Portal enables developers to create and manage their projects efficiently. It provides the following key pages for comprehensive project management:

- **Projects Settings**
- **Home Page**
- **App Store Page**
- **App Configurations Page**
- **Linked Accounts Page**
- **Agent Playground Page**
- **Account Settings**

## Development Setup

1. **Bring up backend in docker compose:**
   Refer to the [backend README](../backend/README.md) to set it up. Make sure you
   complete the [Webhooks](../backend/README.md#webhooks-for-local-end-to-end-development-with-frontend) section of the setup.

1. Make sure you are in the **frontend** directory

1. **Install dependencies:**
   If you're using npm:

   ```bash
   npm install --legacy-peer-deps
   ```

   (Note: This repo uses Next.js 15, which requires React 19 that is
   [stabilized in Dec 05, 2024](https://react.dev/blog/2024/12/05/react-19).
   Some libraries are still upgrading to React 19, so we need to use the
   `--legacy-peer-deps` flag in the mean time.)

1. **Configure Environment Variables:** Copy `.env.example` to `.env`

   ```bash
   cp .env.example .env
   ```

1. **Start the application:**

   ```bash
   npm run dev
   ```

1. **Sign up on the local dev portal:**
   After signup, a new user will be created in the PropelAuth local dev org's test
   environment. PropelAuth will also call the user-created webhook, which will create a
   test project and agent in your local DB for you to use.

## Linting & Testing

This repo uses prettier for formatting, next lint for linting, and vitest for unit tests.

- **Format code:**

  ```bash
  npm run format
  ```

- **Run linters:**

  ```bash
  npm run lint
  ```

- **Run vitest in watch mode:**

  ```bash
  npm run test
  ```

- **Get test coverage:**

  ```bash
  npm run test:coverage
  ```

You can also setup pre-commit hook to run format, lint, and tests when you
commit your code by running (make sure you have [pre-commit](https://pre-commit.com/) installed):

```bash
pre-commit install
```

## Directory Structure

```text
src
├── app (Next.js App Router folder)
│   ├── ... (different pages of the dev portal)
├── components
│   ├── ... (components we created for use in the pages of dev portal)
│   └── ui  (shadcn/ui components we installed)
├── hooks
│   └── use-mobile.tsx
└── lib
│   ├── api          (functions for interacting with the Aipolabs backend API)
│   ├── types        (types of the Aipolabs backend API response)
│   └── utils.ts
└── __test__ (test files, the structure of this folder should be the same as the structure of the src/app folder)
    ├── apps
    ├── linked-accounts
    ├── project-setting
    └── ...
```

## Conventions

- All functions calling the backend API directly should be put in the [src/lib/api](./src/lib/api/) folder.

## Deployment

The Dev Portal is deployed on Vercel: [obnoxiousproxys-projects/aci-dev-portal](https://vercel.com/obnoxiousproxys-projects/aci-dev-portal)

The environment variables need to be set correctly on Vercel: <https://vercel.com/obnoxiousproxys-projects/aci-dev-portal/settings/environment-variables>.

For example, for the Vercel production environment, we set the following environment variables:

```sh
NEXT_PUBLIC_API_URL=https://api.aci.dev
NEXT_PUBLIC_DEV_PORTAL_URL=https://platform.aci.dev
NEXT_PUBLIC_ENVIRONMENT=production
NEXT_PUBLIC_AUTH_URL=<actual_production_propelauth_endpoint>
```