npm package: @fleek-platform/agents-ui
Description: The Fleek Platform Agents UI provides a simple interface for deploying, monitoring, and configuring your agents––making management straightforward
Latest version: 8.38.3

# ⚡️Fleek Platform Agents UI

[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-blue.svg)](https://conventionalcommits.org)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

The Fleek Platform Agents UI provides a simple interface for deploying, monitoring, and configuring your agents––making management straightforward.

## Overview

- [🤖 Install](#-install)
  - [Acessing deprecated version of Agents UI](#acessing-deprecated-version-of-agents-ui)
- [👷 Development](#-development)
  - [Environment variables](#environment-variables)
  - [Development Server](#development-server)
  - [Build](#build)
  - [Preview](#preview)
  - [Stripe Tests](#stripe-tests)
  - [Data fetching](#data-fetching)
  - [Branch Deployment Matrix](#branch-deployment-matrix)
- [💍 Tests](#-tests)
  - [Changeset](#changeset)
  - [Local Package Test](#local-package-test)
- [🧪 Experimental Flags](#experimental-flags)
- [🧸 Basic usage](#-basic-usage)
  - [Interface](#interface)
  - [Example usage](#example-usage)
  - [Using the ChatBox Component](#using-the-chatbox-component)
- [🚀 Package Release](#-package-release)
  - [Release by develop hash](#release-by-develop-hash)
  - [Override organisation registry](#override-organisation-registry)
  - [Create a private GHCR Token](#create-a-private-ghcr-token)
  - [Import by Version in a Host Project](#import-by-version-in-a-host-project)
- [🙏 Contributing](#-contributing)
  - [Branching strategy](#branching-strategy)
  - [Conventional commits](#conventional-commits)
  - [Plugins](#plugins)

## 🤖 Install

Install the package by executing:

```sh
npm i @fleek-platform/agents-ui
```

⚠️ If you're planning to contribute as a developer, you must install [pnpm](https://pnpm.io), otherwise most commands will fail.

For a quick start, learn the [basic usage](#-basic-usage).

### Acessing deprecated version of Agents UI

The deprecated version of [elizaOS Agents UI](https://github.com/fleek-platform/agents-ui/tree/eliza-ui) is available [here](https://github.com/fleek-platform/agents-ui/tree/eliza-ui). The branch `eliza-ui` is maintained througout the transition to revamped dashboard version of `agents-ui` and is detached from the CI release cycles. Get in touch with the team to have it published.

## 👷 Development

For developers looking to contribute to the `@fleek-platform/agents-ui`, [clone](https://github.com/fleekxyz/agents-ui) the repository and follow the [contribution guide](#-contributing).

For runtime we utilize [Nodejs](https://nodejs.org/en/download) and [PNPM](https://pnpm.io/installation) as the package manager.

Next, install the project dependencies:

```sh
pnpm i
```

### Build

The build process generates the static files, put into `./dist` directory, that can be served statically by an HTTP server. 

To generate the build output run:

```sh
pnpm build
```

### Preview

To preview the [build](#build) locally, you can run the command:

```sh
pnpm preview
```

A HTTP server will serve the build output.

### Environment variables

If you'll be interacting with services, you'll need to set up the environment variables.

Create a local file named `.env` and declare the following environment variables for the environment you're interested (below we're using the public~production settings):

```sh
PUBLIC_FLEEK_REST_API_HOST="https://api.fleek.xyz"
PUBLIC_DASHBOARD_APP_URL="https://fleek.xyz/dashboard"
PUBLIC_BEEHIIV_PROXY_SERVER_URL="https://faas-lon1-917a94a7.doserverless.co/api/v1/web/fn-5aaf2a72-1b5b-4ac6-8c42-a2e735a32d8b/main/create-subscription"
PUBLIC_AUTOFUN_CALLBACK_URL="https://auto.fun/callback"
PUBLIC_GRAPHQL_API_URL="https://graphql.service.fleek.xyz/graphql"
PUBLIC_DYNAMIC_ENVIRONMENT_ID="de23a5f0-aaa5-412e-8212-4fb056a3b30d"
PUBLIC_AGENTS_BASE_PATH="/"
PUBLIC_REDIRECT_URL_UNAUTHENTICATED="https://fleek.xyz"
PUBLIC_PERSONA_GENERATOR_API_URL="https://persona-generator.flkservices.io"
PUBLIC_DEV_PORT=3002
PUBLIC_FLEEK_WEBSITE_URL="https://fleek.xyz"
PUBLIC_CUSTOM_AGENTS_URL="https://social-agent.platform.fleek.xyz"
PUBLIC_POSTHOG_HOST="https://us.i.posthog.com"
PUBLIC_POSTHOG_API_KEY="*****"
```

> [!NOTE]  
> The PUBLIC_REDIRECT_URL_UNAUTHENTICATED is primarly used to declare the website URL. Due to other environments, it might be set to something else for different purposes, e.g. testing in repo environment. The URL provided must be valid, e.g. https://fleek.xyz which includes the http protocol. Set it to "false" to hint it is intentional.

The application uses the [getDefined](./src/Eliza/defined.ts) to lookup for environment variables.

### Development Server

During development, the server runs on Vite for fast refresh and module replacement. However, Tailwind CSS styles currently require a manual rebuild when changes are made, as there's no watcher implemented yet. To start development, run these commands in separate terminals:

```sh
pnpm dev
```

### Stripe Tests

Tests can be performed in the [staging](https://fleek-xyz-staging.fleeksandbox.xyz/eliza/) environment due to a sandbox version of stripe.

Here's a quick example of a credit-card number:

```text
5200 8282 8282 8210
```

To learn more visit the documentation [here](https://docs.stripe.com/testing#cards).

### LocationState vs NavigationState

The `locationState` and `navigationStore` serve distinct purposes within the application. While both hold stateful data, they differ in scope and intent:

#### `locationState` (Router Concerned)
- Directly tied to **React Router**.
- Stores minimal metadata about the **current** navigation event.
- Primarily used to track **where the user came from** (`from` property).
- Does **not** persist across pages—only valid within the current navigation context.

Example:
```ts
const { pathname, locationState } = useTypedLocation();
console.log(locationState.from); // Logs previous page if available
```

#### **`navigationStore` (App-Level Data)**
- Holds application-wide navigation-related data **not** strictly tied to routing.
- Stores persistent state needed across multiple pages, such as set avatar, or character files.
- Managed via **Zustand** (`useNavigationStore`), ensuring updates persist beyond a single navigation event.

```tsx
const { navigationStore, setNavigationState } = useNavigationStore();
setNavigationState({ characterFile: 'file-content' });
console.log(navigationStore.characterFile); // 'file-content' persists across pages
```

### Branch Deployment Matrix

This table shows the corresponding deployment URLs for each branch. Note that the availability and state of each URL depends on successful CI/CD build and deployment.

⚠️ The URLs below may be temporarily unavailable during deployments or if a build fails.

```
Branch              |  URL
----------------------------------
develop (latest)    |  https://fleek-agents-staging.fleeksandbox.xyz
main                |  https://fleek-agents-production.fleeksandbox.xyz
```

## 💍 Tests

The project has two category of tests:

- Unit tests, which assert pure functions, e.g. data transformations, calculations, etc, a separate concern over the presentation;
- [TODO] End-to-End (e2e) built on playwright to facility testing the UI/UX interface. The network calls are mocked to facilitate rapid development and focus on the interface;

You can run all tests by executing the command:

```sh
pnpm run test
```

Alternatively, you can inspect the available tests in the package.json scripts section.

For example, run the unit tests

```sh
pnpm run test:unit
```

### Changeset

Manage the versioning of changelog entries.

Declare an intent to release by executing the command and answering the wizard's questions:

```sh
pnpm changeset:add
```

### Local Package Test

Since npm link is a command-line tool for symlinking a local package as a dependency during development. It is commonly used for testing packages before publishing them. But it's common to cause confusion and unexpected behaviour.

Instead of using `pnpm link` for local package testing, use the following command, that's closer to release install.

```sh
pnpm generate:local_package
```

Once successful, the console will display an install command that you can copy and run in your project.

Here's an example that uses npm:

```sh
npm i --no-save <GENERATED_FILE_PATH>
```

> [!WARNING]
> Remove concurrent package name from package.json, e.g. @fleek-platform/agents-ui. The local install doesn't save or modify the package.json. The package.json and lockfiles are only for existing registry versions. You might have to run the clean command to remove any conflicting packages from node_modules, locks, etc.

Alternatively, if you're using an npm-compatible package manager like pnpm, avoid saving or modifying the lock file, e.g:

```sh
npm_config_save=false npm_config_lockfile=false pnpm i <GENERATED_FILE_PATH>
```

Another option is to use the GitHub registry to push any packages you might want to test. Find more about it [here](#override-organisation-registry).

### Data Fetching

We use **React Query** for API interactions, ensuring efficient data fetching, caching, and updates.  

#### Fetching Data  
Queries retrieve data and automatically update when dependencies change. Example:  

```tsx
const { data, isLoading, error } = useAgentStatus({ agentId });
```

**Implementation:**  
```tsx
useQuery({
  queryKey: ['agentStatus', agentId],
  queryFn: () => getAgentStatusById({ accessToken, agentId }),
  enabled: !!accessToken,
});
```

#### Updating Data (Optimistic Updates)  
Mutations modify data, with **instant UI updates** before API confirmation.  

```tsx
const { mutate: updateStatus } = useAgentStatusUpdate({ agentId });
updateStatus('start'); // Instantly reflects UI change
```

**Implementation:**  
```tsx
useMutation({
  mutationFn: (action) => changeAgentStatus({ agentId, accessToken, action }),
  onMutate: (action) => {
    queryClient.cancelQueries(['agentStatus', agentId]);
    queryClient.setQueryData(['agentStatus', agentId], action === 'start');
  },
  onSettled: () => queryClient.invalidateQueries(['agentStatus', agentId]),
});
```
More details: [React Query Documentation](https://tanstack.com/query/latest/docs/react/overview).

## Experimental Flags

Enable experimental features by declaring them as comma separated values of query param `experimental`, e.g. `?experimental=influencers,game`. Set `experimental` to `disable` to clear all!

Here's how you'd enable the feature `influencers` in the staging URL:

```sh
https://fleek-xyz-staging.fleeksandbox.xyz/?experimental=influencers
```

Here's how you'd disable all:

```sh
https://fleek-xyz-staging.fleeksandbox.xyz/?experimental=disable
```

If you'd like to introduce some experimental features and hide it behind this control, you must declare it.

At time of writing this can be found in the [settings](src/settings.ts):

```ts
// Add or remove flags
export const devExperimentalFeatureNames = ['influencers'] as const;
```

You can then show or hide a feature by:

```ts
isExperimentalFlagEnabled('influencers')
```

## 🧸 Basic usage

Package is distributed as ESM module that exports source code, transpiling and processing is left to the host application. To use it, you need to do the following:

1. Make sure that it is included as a dependency.

```ts
// package.json

"dependencies": {
  "@fleek-platform/agents-ui": "*", // specify the correct version
  // ...
}
```

2. Import `ElizaIntegrationLayer` component and pass the required props.

### Interface

Package defines the expected interface inside the [app.tsx](src/app.tsx) component. The host app is expected to pass the following props:

```tsx
// package
// src/app.tsx

export interface ElizaIntegrationLayerProps {
  // auth props
  authStoreInstance: AuthStore;
  getReferralId?: () => string;
  getSubscriptions: getSubscriptionsType;
  getPlans: getPlansType;
  captureEvent?: CaptureEventFn;
  createSubscriptionCheckout: (
    params: CreateSubscriptionCheckoutRequestProps,
  ) => Promise<CreateSubscriptionResponse>;
}

// callback types, please see the source for the exact response shape 
type getSubscriptionsType = (projectId?: string,  token?: string) => Promise<{ ... }>;
type getPlansType = (token?: string) => Promise<{ ... }>;
```

Not all data is passed via props, additional data is passed via the `src/settings.json` common configuration file. Components inside the `src/components/Eliza` import this file. These are the required fields by the package (host app may define other, additional fields):

```ts
// src/settings.json

{
  "elizaPage": {
    "endpoints": {
      "aiAgents": "ai-agents endpoint url"
    },
    "agentsDashboardPage": "dashboard url"
  }
}
```

💡 Note: You must use relative import for this file.

```ts
import settings from '../../../settings.json'; // ✅ will work

import settings from '@base/settings.json'; // ❌ will fail
```

### `basePath` and Router Functionality

The `basePath` is defined as an environment variable `PUBLIC_BASE_PATH` allows you to define a custom base URL for all routes within the Agents UI, making it easier to integrate into applications that have existing routing structures. This is particularly useful when embedding the UI into a larger project with a prefixed path.

Usage

```ts
PUBLIC_AGENTS_BASE_PATH="/agents"
```

With this configuration, all internal routes will be prefixed with /agents. For example:

`/agents/new` → Agent creation

`/agents/drafts/:draftId` → Draft management

`/agents/:agentId` → Agent overview

If `basePath` is not specified, the default behavior assumes root-level navigation.

### Example usage

Example usage inside the host app, e.g. [fleek-platform/website](https://github.com/fleek-platform/website):

```tsx
// src/components/AgentsUI/index.tsx

// import styles
import '@fleek-platform/agents-ui/styles';

// import implementation from the package
import { ElizaIntegrationLayer, api } from '@fleek-platform/agents-ui';

const {
  createSubscription,
  getPlans,
  getSubscriptions,
} = api;

export const AgentsUIIntegration: React.FC = () => {
  const { triggerLoginModal, accessToken, isLoggingIn, isLoggedIn, projectId } =
    useAuthStore();
  const login = () =>
    typeof triggerLoginModal === 'function' && triggerLoginModal(true);

  return (
    <ElizaIntegrationLayer
      getSubscriptions={getSubscriptions}
      getPlans={getPlans}
      createSubscription={createSubscription}
    />
  );
};

const AgentsUI: React.FC = () => <AgentsUIIntegration />;

// to be used in Astro
export default AgentsUI;
```

### Using the ChatBox Component

The ChatBox component provides a text input interface with file attachment capabilities. It was built targeted to chat-like interfaces where you need to collect user input and handle file uploads.

```tsx
import { ChatBox } from '@fleek-platform/agents-ui';

const MyComponent = () => {
  const handleSubmit = async (description: string, files: FileWithPreview[]) => {
    // Handle the submission of text and files
    console.log('Description:', description);
    console.log('Files:', files);
    return true; // Return true on success
  };

  const handleSuccess = () => {
    // Called when submission is successful
    console.log('Submission successful');
  };

  const handleError = (error: Error) => {
    // Handle any errors during submission
    console.error('Submission failed:', error);
  };

  return (
    <ChatBox
      onSubmit={handleSubmit}
      onSuccess={handleSuccess}
      onError={handleError}
      maxFileSize={10 * 1024 * 1024} // Optional: 10MB max file size
    />
  );
};
```

#### Props

- `onSubmit`: (Required) Async function called when the form is submitted. Receives the text description and array of files.
- `onSuccess`: (Optional) Callback function called after successful submission.
- `onError`: (Optional) Callback function called if submission fails.
- `onDescriptionChange`: (Optional) Function called whenever the text input changes.
- `onFilesChange`: (Optional) Function called whenever files are added or removed.
- `maxFileSize`: (Optional) Maximum file size in bytes. Defaults to 10MB.

#### Supported File Types

The component accepts the following file types:
- Text files (.txt)
- PDF documents
- JSON files
- Markdown files
- Images (JPEG, PNG, GIF)

#### Features

- Automatic textarea height adjustment
- File preview for images
- File size validation
- File type validation
- Loading state handling
- Error handling with toast notifications
- Keyboard shortcuts (Enter to submit)

## 🚀 Package Release

TLDR; Use the [Release by develop hash](#release-by-develop-hash). The **main branch** must have a linear strategy, e.g. we don't want contributors to push directly to **main**. At anytime, it should be a subset of **develop**, as we are strictly about preventing source diversion. On production release, the package should be available at [npmjs.org](https://www.npmjs.com/~fleek-platform), for staging [GitHub Registry packages (GHCR)](https://github.com/orgs/fleek-platform/packages).

The main principal to understand is that when a branch is merged into **main** or **develop**, the npm-publisher.yml workflow is triggered to publish packages to the appropriate registry.

For the main branch, packages are published to the [npmjs.org](https://www.npmjs.com/~fleek-platform) registry, ensuring they are available for public use.

Conversely, when changes are merged into the develop branch, packages are published to the [GitHub Registry packages (GHCR)](https://github.com/orgs/fleek-platform/packages)
, which serves as a staging environment.

This setup allows for a clear separation between production-ready packages and those in development.

### Release by develop hash

You can release to production following a linear strategy. This assumes that the convention "main" branch is of linear history and is a subset of the "develop" branch commit history. For example, the team is happy to have "develop" as where the latest version of the project exists, that "main" shouldn't diverge and only contain commits from "develop".

Use-case examples:

- The team has merged some feature branches into develop identified as commit hash "abc123" and want to release upto to the commit history hash "abc123" onto "main". By doing this they expect the build process to occur and deploy into the Fleek Platform
- The team has merged several feature branches into develop identified as commit hashes `commitFeat1`, `commitFeat2` and `commitFeat3` by this historical order. It's decided to release everything in commit history until `commitFeat1`, but not `commitFeat2` and `commitFeat3`. Although, it'd be wiser to keep the feature branches in pending state as "develop" should always be in a ready state for testing and release as the team may want to release some quick hotfixes, etc

To release to production open the actions tab [here](https://github.com/fleek-platform/agents-ui/actions).

Select the "🚀 Release by develop hash" job in the left sidebar. Next, select the "Run workflow" drop-down and provide the required details, e.g. the commit hash of `develop branch` you are interested. Do note that it'll release everything up until the commit hash you select. If you have anything in develop which's not ready, that should be reverted from `develop branch`.

### Override organisation registry

You can override the organisation registry in different ways. For example, you can setup a local `.npmrc` that overrides the organisation `@fleek-platform` registry.

Start by changing to project directory and create or edit a .npmrc file:

```sh
touch .npmrc
```

Use your favourite text editor and put the following content:

```
//npm.pkg.github.com/:_authToken=$PAT
@fleek-platform:registry=https://npm.pkg.github.com
```

The `PAT` is an environment variable for your private authentication token. An authentication token is required for GHCR Registry, as GHCR is our private registry used for testing.

Alternatively, some users prefer to use the npm CLI to authenticate against the organisation scope.

Here's a quick set of instructions to allow to login via NPM CLI.

1) Execute the command npm login with scope and registry URL

```sh
npm login --scope=@fleek-platform --registry=https://npm.pkg.github.com
```

2) Provide a random username, e.g. somebody

```sh
username: somebody
```

3) Put the provided token as the user password

```sh
password: ***
```

Onwards, your registry for `@fleek-platform` will be pointing to private GitHub Registry. Make sure that you logout after testing, as this might cause confusion.

### Create a private GHCR Token

Visit your GitHub user [tokens](https://github.com/settings/tokens).

Create a new token that allows you to:

- Upload packages to GitHub Package Registry, e.g. `write:packages`
- Download packages from GitHub Package Registry, e.g. `read:packages`

### Import by Version in a Host Project

To install the package in any project that wants to use it, run the install command, e.g. we'll use `npm` but you can use the project package manager:

```sh
npm install @fleek-platform/agents-ui@latest
```

Alternatively, you can specify the [package version](https://www.npmjs.com/package/@fleek-platform/agents-ui?activeTab=versions), e.g. replace `x.x.x` by the correct version

```sh
npm install @fleek-platform/agents-ui@x.x.x
```

If you're updating the package version in a project, such as [website](https://github.com/fleek-platform/website), you'll have to create a pull request for the new package version you are updating to.

## 🙏 Contributing

This section guides you through the process of contributing to our open-source project. From creating a feature branch to submitting a pull request, get started by:

1. Fork the project [here](https://github.com/fleekxyz/cli)
2. Create your feature branch using our [branching strategy](#branching-strategy), e.g. `git checkout -b feat/my-new-feature`
3. Run the tests: `pnpm test`
4. Commit your changes by following our [commit conventions](#conventional-commits), e.g. `git commit -m 'chore: 🤖 my contribution description'`
5. Push to the branch, e.g. `git push origin feat/my-new-feature`
6. Create new Pull Request following the corresponding template guidelines

### Branching strategy

The develop branch serves as the main integration branch for features, enhancements, and fixes. It is always in a deployable state and represents the latest development version of the application.

Feature branches are created from the develop branch and are used to develop new features or enhancements. They should be named according to the type of work being done and the scope of the feature and in accordance with conventional commits [here](#conventional-commits).

### Conventional commits

We prefer to commit our work following [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0) conventions. Conventional Commits are a simple way to write commit messages that both people and computers can understand. It help us keep track fo changes in a consistent manner, making it easier to see what was added, changed, or fixed in each commit or update.

The commit messages are formatted as **[type]/[scope]**
The **type** is a short descriptor indicating the nature of the work (e.g., feat, fix, docs, style, refactor, test, chore). This follows the conventional commit types.

The **scope** is a more detailed description of the feature or fix. This could be the component or part of the codebase affected by the change.

Here's an example of different conventional commits messages that you should follow:

```txt
test: 💍 Adding missing tests
feat: 🎸 A new feature
fix: 🐛 A bug fix
chore: 🤖 Build process or auxiliary tool changes
docs: 📝 Documentation only changes
refactor: 💡 A code change that neither fixes a bug or adds a feature
style: 💄 Markup, white-space, formatting, missing semi-colons...
```

### Plugins

To add new plugins to the Agents UI package, you need to follow these steps:

1. Make sure the BE supports it
2. Find the constants.ts file (/src/components/Eliza/utils/constants.ts)
3. Add the plugin name to the `PLUGIN_NAMES` array under the correct category
4. Update the `PLUGINS_MAP` with the new plugin. Follow the same format as the other plugins by defining category, label, description and, optionally, an icon.
5. Update the `SECRETS_PLUGIN_MAP` with the secrets that the plugin need.