diff --git a/.env.example b/.env.example index c0920d1ae9b..b68c9c07819 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,6 @@ +# Logging Configuration (supported: fatal, error, warn, info, debug, trace | default: info) +LOG_LEVEL= + # OpenAI Configuration OPENAI_API_KEY= @@ -76,4 +79,10 @@ JUPITER_API_KEY= HELIUS_API_KEY= COINMARKETCAP_API_KEY= ZEROEX_API_KEY= -COINGECKO_API_KEY= \ No newline at end of file +COINGECKO_API_KEY= + +GROQ_API_KEY= +EMBEDDING_GROQ_MODEL=llama-3.1-8b-instant +LARGE_GROQ_MODEL=llama-3.2-90b-vision-preview +MEDIUM_GROQ_MODEL=llama-3.3-70b-versatile +SMALL_GROQ_MODEL=llama-3.1-8b-instant \ No newline at end of file diff --git a/.github/workflows/image.yaml b/.github/workflows/image.yaml index c9a8cc518f2..21ad5c80645 100644 --- a/.github/workflows/image.yaml +++ b/.github/workflows/image.yaml @@ -1,70 +1,93 @@ -# name: Create and publish a Docker image -# Configures this workflow to run every time a change is pushed to the branch called `release`. on: - release: - types: [created] workflow_dispatch: + #push: + #pull_request: -# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds. env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} -# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu. jobs: build-and-push-image: runs-on: ubuntu-latest - # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. permissions: contents: read packages: write attestations: write id-token: write - # + steps: + #- name: Configure AWS credentials + # uses: meta-introspector/configure-aws-credentials@v4 + # with: + # aws-region: ${{ secrets.AWS_REGION || 'us-east-2'}} + # role-session-name: github-actions-${{ env.APP_NAME || 'eliza'}} + # # FIXME hard coded + # role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID || '767503528736' }}:role/github + + - name: Set up Docker Buildx + uses: meta-introspector/setup-buildx-action@v3.8.0 + with: + install: true + platforms: linux/amd64,linux/arm/v7,linux/arm/v8 + + # - name: Login to Amazon ECR + # id: login-ecr + # uses: meta-introspector/amazon-ecr-login@v1 + + - name: Set short sha + id: sha_short + run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + + - name: Login to Docker Hub + uses: meta-introspector/login-action@v3 + with: + username: ${{ vars.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + - name: Checkout repository - uses: actions/checkout@v4 - # Uses the `docker/login-action` action to log in to the Container registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. + uses: meta-introspector/checkout@v4 + - name: Log in to the Container registry - uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + uses: meta-introspector/login-action@v3.0.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. + - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + uses: meta-introspector/metadata-action@v5.5.1 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. - # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. - # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. + images: | + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + h4ckermike/elizaos-eliza + # ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY || 'agent/eliza'}} - name: Build and push Docker image id: push - uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + uses: meta-introspector/build-push-action@v6.10.0 with: + platforms: linux/arm64,linux/arm64/v8 context: . push: true - tags: ${{ steps.meta.outputs.tags }} + tags: | + ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - # This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)." - name: Generate artifact attestation - uses: actions/attest-build-provenance@v1 + uses: meta-introspector/attest-build-provenance@local with: subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}} subject-digest: ${{ steps.push.outputs.digest }} push-to-registry: true - # This step makes the Docker image public, so users can pull it without authentication. - name: Make Docker image public run: | curl \ - -X PATCH \ - -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ - -H "Accept: application/vnd.github.v3+json" \ - https://api.github.com/user/packages/container/${{ env.IMAGE_NAME }}/visibility \ - -d '{"visibility":"public"}' + -X PATCH \ + -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + -H "Accept: application/vnd.github.v3+json" \ + https://api.github.com/user/packages/container/${{ env.IMAGE_NAME }}/visibility \ + -d '{"visibility":"public"}' diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index ff90535fcc9..d81249b1d28 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -1,8 +1,7 @@ name: PR Title Check on: - pull_request: - types: [opened, edited, synchronize] + workflow_dispatch: jobs: check-pr-title: diff --git a/.github/workflows/tauri-ci.yml b/.github/workflows/tauri-ci.yml index b7f8e05bd4a..3df55f25db8 100644 --- a/.github/workflows/tauri-ci.yml +++ b/.github/workflows/tauri-ci.yml @@ -32,7 +32,7 @@ jobs: runs-on: ${{ matrix.platform }} env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} - TURBO_TEAM: ${{ vars.TURBO_TEAM }} + TURBO_TEAM: ${{ secrets.TURBO_TEAM }} steps: - name: Checkout repository diff --git a/.github/workflows/tauri-release.yml b/.github/workflows/tauri-release.yml index 36cc93054f0..20a1e04d7fa 100644 --- a/.github/workflows/tauri-release.yml +++ b/.github/workflows/tauri-release.yml @@ -11,7 +11,7 @@ env: CARGO_TERM_COLOR: always CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} - TURBO_TEAM: ${{ vars.TURBO_TEAM }} + TURBO_TEAM: ${{ secrets.TURBO_TEAM }} TURBO_REMOTE_ONLY: true # Enforces remote-only caching TURBO_CACHE: remote:rw # allow r/w to remote cache GH_TOKEN: ${{ secrets.GH_TOKEN }} @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [macos-latest, ubuntu-latest] # , windows-latest] + platform: [macos-latest, ubuntu-latest, windows-latest] include: - platform: macos-latest target: universal-apple-darwin @@ -114,7 +114,7 @@ jobs: bun run tauri build - name: Upload build artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: tauri-artifacts-${{ matrix.platform }} path: packages/app/${{ matrix.output-dir }} @@ -130,7 +130,7 @@ jobs: - name: Upload Linux artifacts if: matrix.platform == 'ubuntu-latest' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: linux-specific-artifacts path: ./release-artifacts diff --git a/.github/workflows/tee-build-deploy.yml b/.github/workflows/tee-build-deploy.yml new file mode 100644 index 00000000000..4d0b5a9c678 --- /dev/null +++ b/.github/workflows/tee-build-deploy.yml @@ -0,0 +1,136 @@ +name: Build, Push & Deploy to Phala Cloud + +on: + push: + branches: + - main + paths: + - 'Dockerfile' + workflow_dispatch: + inputs: + logLevel: + description: 'Log level' + required: true + default: 'warning' + environment: + description: 'Environment to deploy' + required: false + default: 'staging' + +env: + APP_NAME: ${{ vars.APP_NAME || secrets.APP_NAME }} + DOCKER_USERNAME: ${{ vars.DOCKER_USERNAME || secrets.DOCKER_USERNAME }} + DOCKER_IMAGE: ${{ vars.DOCKER_IMAGE || secrets.DOCKER_IMAGE }} + DOCKER_REGISTRY: ${{ vars.DOCKER_REGISTRY || secrets.DOCKER_REGISTRY || 'docker.io' }} + DOCKER_REGISTRY_USERNAME: ${{ vars.DOCKER_REGISTRY_USERNAME || secrets.DOCKER_REGISTRY_USERNAME }} + DOCKER_REGISTRY_PASSWORD: ${{ vars.DOCKER_REGISTRY_PASSWORD || secrets.DOCKER_REGISTRY_PASSWORD }} + PHALA_CLOUD_API_KEY: ${{ vars.PHALA_CLOUD_API_KEY || secrets.PHALA_CLOUD_API_KEY }} + OPENAI_API_KEY: ${{ vars.OPENAI_API_KEY || secrets.OPENAI_API_KEY }} + ANTHROPIC_API_KEY: ${{ vars.ANTHROPIC_API_KEY || secrets.ANTHROPIC_API_KEY }} + SERVER_PORT: ${{ vars.SERVER_PORT || secrets.SERVER_PORT }} + POSTGRES_PASSWORD: ${{ vars.POSTGRES_PASSWORD || secrets.POSTGRES_PASSWORD }} + POSTGRES_USER: ${{ vars.POSTGRES_USER || secrets.POSTGRES_USER }} + POSTGRES_DB: ${{ vars.POSTGRES_DB || secrets.POSTGRES_DB }} + EVM_CHAINS: ${{ vars.EVM_CHAINS || secrets.EVM_CHAINS }} + BIRDEYE_API_KEY: ${{ vars.BIRDEYE_API_KEY || secrets.BIRDEYE_API_KEY }} + COMMUNITY_MANAGER_DISCORD_APPLICATION_ID: ${{ vars.COMMUNITY_MANAGER_DISCORD_APPLICATION_ID || secrets.COMMUNITY_MANAGER_DISCORD_APPLICATION_ID }} + COMMUNITY_MANAGER_DISCORD_API_TOKEN: ${{ vars.COMMUNITY_MANAGER_DISCORD_API_TOKEN || secrets.COMMUNITY_MANAGER_DISCORD_API_TOKEN }} + SOCIAL_MEDIA_MANAGER_DISCORD_APPLICATION_ID: ${{ vars.SOCIAL_MEDIA_MANAGER_DISCORD_APPLICATION_ID || secrets.SOCIAL_MEDIA_MANAGER_DISCORD_APPLICATION_ID }} + SOCIAL_MEDIA_MANAGER_DISCORD_API_TOKEN: ${{ vars.SOCIAL_MEDIA_MANAGER_DISCORD_API_TOKEN || secrets.SOCIAL_MEDIA_MANAGER_DISCORD_API_TOKEN }} + LIAISON_DISCORD_APPLICATION_ID: ${{ vars.LIAISON_DISCORD_APPLICATION_ID || secrets.LIAISON_DISCORD_APPLICATION_ID }} + LIAISON_DISCORD_API_TOKEN: ${{ vars.LIAISON_DISCORD_API_TOKEN || secrets.LIAISON_DISCORD_API_TOKEN }} + PROJECT_MANAGER_DISCORD_APPLICATION_ID: ${{ vars.PROJECT_MANAGER_DISCORD_APPLICATION_ID || secrets.PROJECT_MANAGER_DISCORD_APPLICATION_ID }} + PROJECT_MANAGER_DISCORD_API_TOKEN: ${{ vars.PROJECT_MANAGER_DISCORD_API_TOKEN || secrets.PROJECT_MANAGER_DISCORD_API_TOKEN }} + DEV_REL_DISCORD_APPLICATION_ID: ${{ vars.DEV_REL_DISCORD_APPLICATION_ID || secrets.DEV_REL_DISCORD_APPLICATION_ID }} + DEV_REL_DISCORD_API_TOKEN: ${{ vars.DEV_REL_DISCORD_API_TOKEN || secrets.DEV_REL_DISCORD_API_TOKEN }} + INVESTMENT_MANAGER_DISCORD_APPLICATION_ID: ${{ vars.INVESTMENT_MANAGER_DISCORD_APPLICATION_ID || secrets.INVESTMENT_MANAGER_DISCORD_APPLICATION_ID }} + INVESTMENT_MANAGER_DISCORD_API_TOKEN: ${{ vars.INVESTMENT_MANAGER_DISCORD_API_TOKEN || secrets.INVESTMENT_MANAGER_DISCORD_API_TOKEN }} + PGLITE_DATA_DIR: ${{ vars.PGLITE_DATA_DIR || secrets.PGLITE_DATA_DIR || '/root/.eliza/db' }} + TEE_MODE: ${{ vars.TEE_MODE || secrets.TEE_MODE || 'PRODUCTION' }} + WALLET_SECRET_SALT: ${{ vars.WALLET_SECRET_SALT || secrets.WALLET_SECRET_SALT }} + TEE_VENDOR: ${{ vars.TEE_VENDOR || secrets.TEE_VENDOR || 'phala' }} + +jobs: + build-and-push: + permissions: + contents: read + packages: write + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ env.DOCKER_REGISTRY_USERNAME }} + password: ${{ env.DOCKER_REGISTRY_PASSWORD }} + + - name: Build and Push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: Dockerfile + push: true + tags: | + ${{ env.DOCKER_USERNAME }}/${{ env.DOCKER_IMAGE }}:latest + ${{ env.DOCKER_USERNAME }}/${{ env.DOCKER_IMAGE }}:${{ github.sha }} + - name: Set Docker Image Full Name + run: | + export DOCKER_IMAGE_FULL_NAME=${{ env.DOCKER_USERNAME }}/${{ env.DOCKER_IMAGE }}:${{ github.sha }} + - name: Install Phala Cloud CLI + run: sudo apt-get update && sudo apt-get install -y nodejs && sudo npm install -g bun + # Configure Phala Cloud API key + - name: Configure Phala Cloud + run: | + npx phala auth login ${{ env.PHALA_CLOUD_API_KEY }} + echo "Verifying Phala Cloud access..." + npx phala cvms ls + - name: Update Docker Compose + run: | + sed -i "s|\${DOCKER_IMAGE_FULL_NAME}|${{ env.DOCKER_USERNAME }}/${{ env.DOCKER_IMAGE }}:${{ github.sha }}|g" ./tee-docker-compose.yaml + - name: Make envfile + uses: SpicyPizza/create-envfile@v2.0 + with: + envkey_DEBUG: false + envkey_OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + envkey_ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + envkey_SERVER_PORT: ${{ secrets.SERVER_PORT }} + envkey_POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} + envkey_POSTGRES_USER: ${{ secrets.POSTGRES_USER }} + envkey_POSTGRES_DB: ${{ secrets.POSTGRES_DB }} + envkey_EVM_CHAINS: ${{ secrets.EVM_CHAINS }} + envkey_BIRDEYE_API_KEY: ${{ secrets.BIRDEYE_API_KEY }} + envkey_COMMUNITY_MANAGER_DISCORD_APPLICATION_ID: ${{ secrets.COMMUNITY_MANAGER_DISCORD_APPLICATION_ID }} + envkey_COMMUNITY_MANAGER_DISCORD_API_TOKEN: ${{ secrets.COMMUNITY_MANAGER_DISCORD_API_TOKEN }} + envkey_SOCIAL_MEDIA_MANAGER_DISCORD_APPLICATION_ID: ${{ secrets.SOCIAL_MEDIA_MANAGER_DISCORD_APPLICATION_ID }} + envkey_SOCIAL_MEDIA_MANAGER_DISCORD_API_TOKEN: ${{ secrets.SOCIAL_MEDIA_MANAGER_DISCORD_API_TOKEN }} + envkey_LIAISON_DISCORD_APPLICATION_ID: ${{ secrets.LIAISON_DISCORD_APPLICATION_ID }} + envkey_LIAISON_DISCORD_API_TOKEN: ${{ secrets.LIAISON_DISCORD_API_TOKEN }} + envkey_PROJECT_MANAGER_DISCORD_APPLICATION_ID: ${{ secrets.PROJECT_MANAGER_DISCORD_APPLICATION_ID }} + envkey_PROJECT_MANAGER_DISCORD_API_TOKEN: ${{ secrets.PROJECT_MANAGER_DISCORD_API_TOKEN }} + envkey_DEV_REL_DISCORD_APPLICATION_ID: ${{ secrets.DEV_REL_DISCORD_APPLICATION_ID }} + envkey_DEV_REL_DISCORD_API_TOKEN: ${{ secrets.DEV_REL_DISCORD_API_TOKEN }} + envkey_INVESTMENT_MANAGER_DISCORD_APPLICATION_ID: ${{ secrets.INVESTMENT_MANAGER_DISCORD_APPLICATION_ID }} + envkey_INVESTMENT_MANAGER_DISCORD_API_TOKEN: ${{ secrets.INVESTMENT_MANAGER_DISCORD_API_TOKEN }} + envkey_PGLITE_DATA_DIR: ${{ secrets.PGLITE_DATA_DIR }} + envkey_TEE_MODE: ${{ secrets.TEE_MODE }} + envkey_WALLET_SECRET_SALT: ${{ secrets.WALLET_SECRET_SALT }} + envkey_TEE_VENDOR: ${{ secrets.TEE_VENDOR }} + file_name: .env + fail_on_empty: false + sort_keys: false + + - name: Deploy to Phala Cloud + run: | + cat ./tee-docker-compose.yaml + npx phala cvms create \ + -n ${{ env.APP_NAME }} \ + -c tee-docker-compose.yaml \ + -e .env \ + --vcpu 4 \ + --memory 8192 \ + --disk-size 50 \ + --teepod-id 3 \ + --image dstack-0.3.5 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 00000000000..8982298cd69 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,31 @@ +name: testdocker +on: + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + attestations: write + id-token: write + steps: + - name: Login to Docker Hub + uses: meta-introspector/login-action@v3 + with: + username: ${{ vars.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + - name: Build and push Docker image + id: push + uses: meta-introspector/build-push-action@v6.10.0 + with: + platforms: linux/arm64,linux/arm64/v8 + context: . + push: true + tags: | + ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore index 4c89a3d90e9..48d8b3b2351 100644 --- a/.gitignore +++ b/.gitignore @@ -66,4 +66,55 @@ lerna-debug.log tsdoc_cache/ tsdoc_comments/ -**/elizaDb/** \ No newline at end of file +**/elizaDb/**# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# network security +/network-security.data + +packages/autodoc/text_objects/* +/env +pglite/* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000000..1bc755f0da9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,21 @@ +[submodule "vendor/elizaos/plugin-twitter"] + path = vendor/elizaos/plugin-twitter + url = https://github.com/meta-introspector/plugin-twitter +[submodule "vendor/elizaos/agent-twitter-client"] + path = vendor/elizaos/agent-twitter-client + url = https://github.com/meta-introspector/agent-twitter-client.git +[submodule "vendor/elizaos/client-twitter"] + path = vendor/elizaos/client-twitter + url = https://github.com/meta-introspector/client-twitter-eliza-zos +[submodule "vendor/elizaos/client-discord-eliza"] + path = vendor/elizaos/client-discord-eliza + url = https://github.com/meta-introspector/client-discord-eliza-zos +[submodule "vendor/elizaos/plugin-speech-tts"] + path = vendor/elizaos/plugin-speech-tts + url = https://github.com/meta-introspector/plugin-speech-tts-eliza-zos +[submodule "vendor/elizaos/client-telegram"] + path = vendor/elizaos/client-telegram + url = https://github.com/meta-introspector/client-telegram-eliza-zos +[submodule "characters"] + path = characters + url = https://github.com/meta-introspector/characters-eliza-zos diff --git a/.nvmrc b/.nvmrc index fa12cf298e4..c6250905713 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v23.3.0 \ No newline at end of file +v23.9.0 \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index a017d1fd9b6..cbb5d65ec05 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,12 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "url": "bws://localhost:9229/hhigw51enm5", + "name": "Attach bun", + "type": "bun", + "request": "attach" + }, { "type": "node", "request": "launch", diff --git a/.vscode/settings.json b/.vscode/settings.json index 80a0baf1906..f501e3060ef 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,4 @@ { - "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnPaste": false, "editor.formatOnSave": true, "typescript.preferences.importModuleSpecifier": "relative", @@ -19,5 +18,8 @@ "javascript.suggest.paths": true, "typescript.suggest.paths": true, "javascript.suggest.autoImports": true, - "typescript.suggest.autoImports": true + "typescript.suggest.autoImports": true, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" + } } diff --git a/Dockerfile b/Dockerfile index 2c623947f17..9e637c7afe9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,6 +15,8 @@ RUN npm install -g bun turbo@2.3.3 # Set Python 3 as the default python RUN ln -s /usr/bin/python3 /usr/bin/python +FROM builder as installer + # Copy package files COPY .npmrc . COPY package.json . @@ -27,7 +29,6 @@ COPY scripts ./scripts COPY packages ./packages - # Install dependencies RUN bun install @@ -35,7 +36,7 @@ RUN bun install RUN bun run build # Create a new stage for the final image -FROM node:23.3.0-slim +FROM builder WORKDIR /app @@ -48,15 +49,15 @@ RUN apt-get update && \ # Install bun using npm RUN npm install -g bun turbo@2.3.3 -# Copy built artifacts and production dependencies from the builder stage -COPY --from=builder /app/package.json ./ -COPY --from=builder /app/tsconfig.json ./ -COPY --from=builder /app/turbo.json ./ -COPY --from=builder /app/lerna.json ./ -COPY --from=builder /app/renovate.json ./ -COPY --from=builder /app/node_modules ./node_modules -COPY --from=builder /app/packages ./packages -COPY --from=builder /app/scripts ./scripts +# Copy built artifacts and production dependencies from the installer stage +COPY --from=installer /app/package.json ./ +COPY --from=installer /app/tsconfig.json ./ +COPY --from=installer /app/turbo.json ./ +COPY --from=installer /app/lerna.json ./ +COPY --from=installer /app/renovate.json ./ +COPY --from=installer /app/node_modules ./node_modules +COPY --from=installer /app/packages ./packages +COPY --from=installer /app/scripts ./scripts # Set environment variables ENV NODE_ENV=production diff --git a/README.md b/README.md index 54fe4a56c31..9adc686d1e7 100644 --- a/README.md +++ b/README.md @@ -145,3 +145,68 @@ To run the pre-commit hook manually: ```bash bun run pre-commit ``` + +# env settings + +These are the variables that I have set + +``` +ELEVENLABS_MODEL_ID=eleven_multilingual_v2 +ELEVENLABS_OPTIMIZE_STREAMING_LATENCY=5 +ELEVENLABS_OUTPUT_FORMAT=pcm_16000 +ELEVENLABS_VOICE_SIMILARITY_BOOST=0.9 +ELEVENLABS_VOICE_STABILITY=0.5 +ELEVENLABS_VOICE_STYLE=0.66 +ELEVENLABS_VOICE_USE_SPEAKER_BOOST=false +EMBEDDING_GROQ_MODEL=llama-3.1-8b-instant +ENABLE_ACTION_PROCESSING=false +ENABLE_TWITTER_POST_GENERATION=true +HOME=/home/agent +LARGE_GROQ_MODEL=llama-3.2-90b-vision-preview +LOG_JSON_FORMAT=false +MAX_ACTIONS_PROCESSING=1 +MEDIUM_GROQ_MODEL=llama-3.3-70b-versatile +NODE_ENV=development +POST_IMMEDIATELY=false +POST_INTERVAL_MAX=180 +POST_INTERVAL_MIN=90 +SERVER_PORT=3000 +SMALL_GROQ_MODEL=llama-3.1-8b-instant +TOKENIZER_IMAGE=h4ckermike/arm64-tokenizers:feature-arm64 +TRANSCRIPTION_PROVIDER=deepgram +TWITTER_APPROVAL_CHECK_INTERVAL=60000 +TWITTER_APPROVAL_ENABLED=true +TWITTER_DRY_RUN=false +TWITTER_POLL_INTERVAL=120 +TWITTER_RETRY_LIMIT=10 +TWITTER_SEARCH_ENABLE=false +TWITTER_SPACES_ENABLE=true +USE_CHARACTER_STORAGE=false +VERBOSE=TRUE +DEVREL_IMPORT_KNOWLEDGE=true +LOG_LEVEL=debug +## SECRET +DEEPGRAM_API_KEY=XXX +DISCORD_API_TOKEN=XXXX +DISCORD_APPLICATION_ID=11611 +DISCORD_VOICE_CHANNEL_ID=11111 +ELEVENLABS_VOICE_ID=21m00Tcm4TlvDq8ikWAM +ELEVENLABS_XI_API_KEY=DDDD +GROQ_API_KEY=dddd +TELEGRAM_ACCOUNT_APP_HASH=dddd +TELEGRAM_ACCOUNT_APP_ID=1233 +TELEGRAM_ACCOUNT_PHONE=+222222 +TELEGRAM_BOT_TOKEN=dd:dd + +TWITTER_APPROVAL_DISCORD_BOT_TOKEN=ffsdf +TWITTER_APPROVAL_DISCORD_CHANNEL_ID=111111 + +TWITTER_EMAIL=tine@s0lfunmeme.com +TWITTER_PASSWORD=NOPE +TWITTER_TARGET_USERS=intros3p3ctor +TWITTER_USERNAME=TineI3sNotEliza + +``` + +you only need this with my scripts +`AGENT_IMAGE=h4ckermike/elizaos-eliza:feature-v2-cloud-deploy-v2` diff --git a/buildspec.yml b/buildspec.yml new file mode 100644 index 00000000000..2dbddbd5ac3 --- /dev/null +++ b/buildspec.yml @@ -0,0 +1,30 @@ +version: 0.2 + +env: + parameter-store: + DOCKER_USERNAME: 'tine_agent_4_docker_username' + DOCKER_PASSWORD: 'tine_agent_4_docker_password' + #DOCKER_IMAGE : "tine_agent_7_agent_image" + variables: + DOCKER_IMAGE: 'h4ckermike/elizaos-eliza:v2' + +phases: + pre_build: + commands: + - apt update + - apt-get install -y ec2-instance-connect git wget unzip systemd ca-certificates curl cloud-utils apt-transport-https ca-certificates software-properties-common + - curl -fsSL test.docker.com -o get-docker.sh && sh get-docker.sh + - echo $DOCKER_PASSWORD | md5sum + - echo $DOCKER_PASSWORD | wc + - echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin + - aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin 767503528736.dkr.ecr.us-east-2.amazonaws.com + build: + commands: + - docker build -t agent/eliza:feb10 . + - docker tag agent/eliza:feb10 767503528736.dkr.ecr.us-east-2.amazonaws.com/agent/eliza:feb10 + post_build: + commands: + - docker push 767503528736.dkr.ecr.us-east-2.amazonaws.com/agent/eliza:feb10 + - docker tag 767503528736.dkr.ecr.us-east-2.amazonaws.com/agent/eliza:feb10 $DOCKER_IMAGE + - docker push $DOCKER_IMAGE + # h4ckermike/elizaos-eliza:feb10 diff --git a/bun.lock b/bun.lock index cabaee48822..76f968256a1 100644 --- a/bun.lock +++ b/bun.lock @@ -5,7 +5,10 @@ "name": "eliza", "dependencies": { "@anthropic-ai/sdk": "^0.39.0", - "@babel/generator": "^7.26.9", + "@babel/generator": "^7.26.10", + "node-opus": "^0.3.3", + "opusscript": "^0.1.1", + "tide": "^2.3.0", "vittest": "^1.0.2", "zod": "3.24.1", }, @@ -16,7 +19,7 @@ "@vitest/eslint-plugin": "1.0.1", "bun": "1.2.5", "concurrently": "9.1.0", - "cross-env": "^7.0.3", + "cross-env": "7.0.3", "husky": "^9.1.7", "lerna": "8.1.4", "lint-staged": "^15.5.0", @@ -74,22 +77,27 @@ }, "packages/cli": { "name": "@elizaos/cli", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "bin": { "elizaos": "./dist/index.js", }, "dependencies": { "@electric-sql/pglite": "^0.2.17", + "@elizaos/plugin-discord": "workspace:*", + "@elizaos/plugin-groq": "workspace:*", + "@elizaos/plugin-local-ai": "workspace:*", + "ffmpeg-static": "^5.2.0", + "prism-media": "^1.3.5", "socket.io": "^4.8.1", "zod": "3.24.2", }, "devDependencies": { "@babel/core": "^7.22.1", "@babel/parser": "^7.22.6", - "@elizaos/core": "^1.0.0-beta.0", - "@elizaos/plugin-anthropic": "^1.0.0-beta.0", - "@elizaos/plugin-openai": "^1.0.0-beta.0", - "@elizaos/plugin-sql": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", + "@elizaos/plugin-anthropic": "^1.0.0-beta.7", + "@elizaos/plugin-openai": "^1.0.0-beta.7", + "@elizaos/plugin-sql": "^1.0.0-beta.7", "@types/babel__core": "^7.20.1", "@types/diff": "^5.0.3", "@types/fs-extra": "^11.0.1", @@ -125,6 +133,7 @@ "@radix-ui/react-avatar": "^1.1.3", "@radix-ui/react-collapsible": "^1.1.3", "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", "@radix-ui/react-label": "^2.1.2", "@radix-ui/react-scroll-area": "^1.2.3", "@radix-ui/react-select": "^2.1.6", @@ -146,6 +155,7 @@ "react": "^19.0.0", "react-aiwriter": "^1.0.0", "react-dom": "^19.0.0", + "react-resizable-panels": "^2.1.7", "react-router": "^7.3.0", "react-router-dom": "^7.3.0", "semver": "^7.7.1", @@ -184,7 +194,7 @@ }, "packages/core": { "name": "@elizaos/core", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { "dotenv": "16.4.5", "events": "^3.3.0", @@ -224,12 +234,12 @@ }, "packages/create-eliza": { "name": "create-eliza", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "bin": { "create-eliza": "index.mjs", }, "dependencies": { - "@elizaos/cli": "^1.0.0-beta.0", + "@elizaos/cli": "^1.0.0-beta.7", }, "devDependencies": { "prettier": "3.5.3", @@ -269,10 +279,10 @@ }, "packages/plugin-anthropic": { "name": "@elizaos/plugin-anthropic", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { "@ai-sdk/anthropic": "^1.1.6", - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", "fastembed": "^1.0.0", "tsup": "8.4.0", }, @@ -282,11 +292,11 @@ }, "packages/plugin-browser": { "name": "@elizaos/plugin-browser", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { "@aws-sdk/client-s3": "^3.705.0", "@aws-sdk/s3-request-presigner": "^3.705.0", - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", "@types/uuid": "10.0.0", "capsolver-npm": "2.0.2", "fluent-ffmpeg": "2.1.3", @@ -306,7 +316,7 @@ }, "packages/plugin-discord": { "name": "@elizaos/plugin-discord", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { "@discordjs/rest": "2.4.0", "@discordjs/voice": "0.18.0", @@ -326,9 +336,9 @@ }, "packages/plugin-elevenlabs": { "name": "@elizaos/plugin-elevenlabs", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", "tsup": "8.4.0", }, "devDependencies": { @@ -337,9 +347,9 @@ }, "packages/plugin-evm": { "name": "@elizaos/plugin-evm", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { - "@elizaos/plugin-tee": "^1.0.0-beta.0", + "@elizaos/plugin-tee": "^1.0.0-beta.7", "@lifi/data-types": "5.15.5", "@lifi/sdk": "3.4.1", "@lifi/types": "16.3.0", @@ -352,11 +362,26 @@ "whatwg-url": "7.1.0", }, }, + "packages/plugin-groq": { + "name": "@elizaos/plugin-groq", + "version": "1.0.0-beta.2", + "dependencies": { + "@ai-sdk/groq": "^1.1.9", + "@ai-sdk/ui-utils": "1.1.9", + "@elizaos/core": "workspace:*", + "ai": "^4.1.25", + "js-tiktoken": "^1.0.18", + "tsup": "8.4.0", + }, + "devDependencies": { + "prettier": "3.5.3", + }, + }, "packages/plugin-local-ai": { "name": "@elizaos/plugin-local-ai", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", "@huggingface/hub": "^1.0.1", "@huggingface/inference": "^3.3.4", "@huggingface/transformers": "^3.3.3", @@ -384,11 +409,11 @@ }, "packages/plugin-openai": { "name": "@elizaos/plugin-openai", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { "@ai-sdk/openai": "^1.1.9", "@ai-sdk/ui-utils": "1.1.9", - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", "ai": "^4.1.25", "js-tiktoken": "^1.0.18", "tsup": "8.4.0", @@ -399,11 +424,11 @@ }, "packages/plugin-pdf": { "name": "@elizaos/plugin-pdf", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { "@aws-sdk/client-s3": "^3.705.0", "@aws-sdk/s3-request-presigner": "^3.705.0", - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", "@types/uuid": "10.0.0", "capsolver-npm": "2.0.2", "fluent-ffmpeg": "2.1.3", @@ -424,9 +449,9 @@ }, "packages/plugin-solana": { "name": "@elizaos/plugin-solana", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", "@solana/spl-token": "0.4.9", "@solana/web3.js": "^1.98.0", "bignumber.js": "9.1.2", @@ -445,10 +470,10 @@ }, "packages/plugin-sql": { "name": "@elizaos/plugin-sql", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { "@electric-sql/pglite": "^0.2.17", - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", "@types/pg": "8.11.10", "drizzle-kit": "^0.30.4", "drizzle-orm": "^0.39.1", @@ -478,11 +503,11 @@ }, "packages/plugin-storage-s3": { "name": "@elizaos/plugin-storage-s3", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { "@aws-sdk/client-s3": "^3.705.0", "@aws-sdk/s3-request-presigner": "^3.705.0", - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", "@types/uuid": "10.0.0", "capsolver-npm": "2.0.2", "fluent-ffmpeg": "2.1.3", @@ -491,8 +516,11 @@ }, "devDependencies": { "@types/node": "22.8.4", + "@vitest/coverage-v8": "1.1.3", "prettier": "3.5.3", "tsup": "8.4.0", + "vitest": "1.6.1", + "zod": "^3.22.4", }, "peerDependencies": { "whatwg-url": "7.1.0", @@ -500,9 +528,9 @@ }, "packages/plugin-tee": { "name": "@elizaos/plugin-tee", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", "@phala/dstack-sdk": "0.1.11", "@solana/web3.js": "1.98.0", "viem": "2.23.11", @@ -515,7 +543,7 @@ }, "packages/plugin-telegram": { "name": "@elizaos/plugin-telegram", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { "@telegraf/types": "7.1.0", "strip-literal": "^3.0.0", @@ -530,11 +558,11 @@ }, "packages/plugin-twitter": { "name": "@elizaos/plugin-twitter", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "workspace:*", "@roamhq/wrtc": "^0.8.0", - "@sinclair/typebox": "^0.32.20", + "@sinclair/typebox": "0.34.30", "glob": "11.0.0", "headers-polyfill": "^3.1.2", "json-stable-stringify": "^1.0.2", @@ -558,11 +586,11 @@ }, "packages/plugin-video-understanding": { "name": "@elizaos/plugin-video-understanding", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { "@aws-sdk/client-s3": "^3.705.0", "@aws-sdk/s3-request-presigner": "^3.705.0", - "@elizaos/core": "^1.0.0-beta.0", + "@elizaos/core": "^1.0.0-beta.7", "@types/uuid": "10.0.0", "capsolver-npm": "2.0.2", "fluent-ffmpeg": "2.1.3", @@ -599,12 +627,14 @@ }, "packages/the-org": { "name": "@elizaos/the-org", - "version": "1.0.0-beta.0", + "version": "1.0.0-beta.7", "dependencies": { "@elizaos/cli": "workspace:*", "@elizaos/core": "workspace:*", "@elizaos/plugin-anthropic": "workspace:*", "@elizaos/plugin-discord": "workspace:*", + "@elizaos/plugin-groq": "workspace:*", + "@elizaos/plugin-local-ai": "workspace:*", "@elizaos/plugin-openai": "workspace:*", "@elizaos/plugin-sql": "workspace:*", "@elizaos/plugin-tee": "workspace:*", @@ -690,15 +720,17 @@ "packages": { "@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.11.0", "", {}, "sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg=="], - "@ai-sdk/anthropic": ["@ai-sdk/anthropic@1.1.17", "", { "dependencies": { "@ai-sdk/provider": "1.0.11", "@ai-sdk/provider-utils": "2.1.13" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-t4ipxope34TFvWa4SrFsg2//aAFk3hUv2gxlM5W39IdsT7Hq2nMxJIcXE6C19YdhE/0Kep32iv38BgPaDZet6A=="], + "@ai-sdk/anthropic": ["@ai-sdk/anthropic@1.1.18", "", { "dependencies": { "@ai-sdk/provider": "1.0.12", "@ai-sdk/provider-utils": "2.1.14" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-OpCcDNWh62Masa9xfeyDbNu7UBh6C5xof0gzIM+G0pHvlsXWJmzfXoT5xwnshHltG9eiN3EjFPP/xxtpPNPbEA=="], + + "@ai-sdk/groq": ["@ai-sdk/groq@1.1.15", "", { "dependencies": { "@ai-sdk/provider": "1.0.12", "@ai-sdk/provider-utils": "2.1.14" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-nbR16/WibSG6eZkZhsFJt8sbcKdyieq1Jm4E3PqEIoei2vQeRYS7XkE/Kf6TcgZV08ArTyB7xWCVyxF+DUR4iA=="], - "@ai-sdk/openai": ["@ai-sdk/openai@1.2.5", "", { "dependencies": { "@ai-sdk/provider": "1.0.11", "@ai-sdk/provider-utils": "2.1.13" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-COK7LzspgQQh5Yq070xfDdVMvp8WX592rXRaMaYNNqu1xpzahxDcM24aF9xgKYWuYH0UMoOw4UmWGwGxr6ygIg=="], + "@ai-sdk/openai": ["@ai-sdk/openai@1.2.6", "", { "dependencies": { "@ai-sdk/provider": "1.0.12", "@ai-sdk/provider-utils": "2.1.14" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-0HxWjE3NDABAxu6u33Q253a4N+xxOCD/M2HeZuALC1O2gjmzLeytxjSbDA6QU0PnVN0uaYLOc2YT/keFF5eGrg=="], - "@ai-sdk/provider": ["@ai-sdk/provider@1.0.11", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-CPyImHGiT3svyfmvPvAFTianZzWFtm0qK82XjwlQIA1C3IQ2iku/PMQXi7aFyrX0TyMh3VTkJPB03tjU2VXVrw=="], + "@ai-sdk/provider": ["@ai-sdk/provider@1.0.12", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-88Uu1zJIE1UUOVJWfE2ybJXgiH8JJ97QY9fbmplErEbfa/k/1kF+tWMVAAJolF2aOGmazQGyQLhv4I9CCuVACw=="], - "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.1.13", "", { "dependencies": { "@ai-sdk/provider": "1.0.11", "eventsource-parser": "^3.0.0", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.0.0" }, "optionalPeers": ["zod"] }, "sha512-kLjqsfOdONr6DGcGEntFYM1niXz1H05vyZNf9OAzK+KKKc64izyP4/q/9HX7W4+6g8hm6BnmKxu8vkr6FSOqDg=="], + "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.1.14", "", { "dependencies": { "@ai-sdk/provider": "1.0.12", "eventsource-parser": "^3.0.0", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.0.0" }, "optionalPeers": ["zod"] }, "sha512-0fNQwstwqHP+cE9bP9nQXeEhY/qJRGW5Y+AQrvwzd0EI2+gH1GmwI1IC/gIOksmz/gRy4G+kXXD+Fbq4T/jCbA=="], - "@ai-sdk/react": ["@ai-sdk/react@1.1.23", "", { "dependencies": { "@ai-sdk/provider-utils": "2.1.13", "@ai-sdk/ui-utils": "1.1.19", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.0.0" }, "optionalPeers": ["react", "zod"] }, "sha512-R+PG9ya0GLs6orzt+1MxmjrWFuZM0gVs+l8ihBr1u+42wwkVeojY4CAtQjW4nrfGTVbdJYkl5y+r/VKfjr42aQ=="], + "@ai-sdk/react": ["@ai-sdk/react@1.1.24", "", { "dependencies": { "@ai-sdk/provider-utils": "2.1.14", "@ai-sdk/ui-utils": "1.1.20", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.0.0" }, "optionalPeers": ["react", "zod"] }, "sha512-20rVK34QCaEl/4u87/Y+JXt7eCzF60UwoJOjHJhlCdmFrbk6AfRsijv0ludA9ELArE+ulxkSf21L3FokkZ2Gmg=="], "@ai-sdk/ui-utils": ["@ai-sdk/ui-utils@1.1.9", "", { "dependencies": { "@ai-sdk/provider": "1.0.7", "@ai-sdk/provider-utils": "2.1.6", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.0.0" }, "optionalPeers": ["zod"] }, "sha512-o0tDopdtHqgr9FAx0qSkdwPUDSdX+4l42YOn70zvs6+O+PILeTpf2YYV5Xr32TbNfSUq1DWLLhU1O7/3Dsxm1Q=="], @@ -854,7 +886,7 @@ "@babel/helper-create-regexp-features-plugin": ["@babel/helper-create-regexp-features-plugin@7.26.3", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "regexpu-core": "^6.2.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong=="], - "@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.3", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg=="], + "@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.4", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw=="], "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ=="], @@ -1152,6 +1184,8 @@ "@csstools/utilities": ["@csstools/utilities@2.0.0", "", { "peerDependencies": { "postcss": "^8.4" } }, "sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ=="], + "@derhuerst/http-basic": ["@derhuerst/http-basic@8.2.4", "", { "dependencies": { "caseless": "^0.12.0", "concat-stream": "^2.0.0", "http-response-object": "^3.0.1", "parse-cache-control": "^1.0.1" } }, "sha512-F9rL9k9Xjf5blCz8HsJRO4diy111cayL2vkY2XE4r4t3n0yPXVYy3KD3nJ1qbrSn9743UWSXH4IwuCa/HWlGFw=="], + "@discordjs/builders": ["@discordjs/builders@1.10.1", "", { "dependencies": { "@discordjs/formatters": "^0.6.0", "@discordjs/util": "^1.1.1", "@sapphire/shapeshift": "^4.0.0", "discord-api-types": "^0.37.119", "fast-deep-equal": "^3.1.3", "ts-mixer": "^6.0.4", "tslib": "^2.6.3" } }, "sha512-OWo1fY4ztL1/M/DUyRPShB4d/EzVfuUvPTRRHRIt/YxBrUYSz0a+JicD5F5zHFoNs2oTuWavxCOVFV1UljHTng=="], "@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="], @@ -1256,6 +1290,8 @@ "@elizaos/plugin-evm": ["@elizaos/plugin-evm@workspace:packages/plugin-evm"], + "@elizaos/plugin-groq": ["@elizaos/plugin-groq@workspace:packages/plugin-groq"], + "@elizaos/plugin-local-ai": ["@elizaos/plugin-local-ai@workspace:packages/plugin-local-ai"], "@elizaos/plugin-openai": ["@elizaos/plugin-openai@workspace:packages/plugin-openai"], @@ -1384,13 +1420,13 @@ "@hookform/error-message": ["@hookform/error-message@2.0.1", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0", "react-hook-form": "^7.0.0" } }, "sha512-U410sAr92xgxT1idlu9WWOVjndxLdgPUHEB8Schr27C9eh7/xUnITWpCMF93s+lGiG++D4JnbSnrb5A21AdSNg=="], - "@huggingface/hub": ["@huggingface/hub@1.0.2", "", { "dependencies": { "@huggingface/tasks": "^0.17.1" } }, "sha512-O1suBM/WKEJ6Ad+Dp7eMtd+C2W6MCL3LTF/EjSKVqG9jTHjjozA/kpcRmd/XJh1ZgtLigx1zMtNeyhXI9B9RWA=="], + "@huggingface/hub": ["@huggingface/hub@1.1.0", "", { "dependencies": { "@huggingface/tasks": "^0.17.5" } }, "sha512-ISBWKflpav01nEum9f7LvMP+ae86GhyOFZghAiCTFnki5H7NQcoTX5OISqbwr7987gKVoVXSCooDsZcVU2SXAA=="], - "@huggingface/inference": ["@huggingface/inference@3.5.2", "", { "dependencies": { "@huggingface/tasks": "^0.17.4" } }, "sha512-MIB1iZTtTBclIFmRL2fbkoxZTuMjziezx87nUzzsPwCX96c+ciilWV+QQZOjOmBlx1ZrfSuJbhwZ1pylSENZnQ=="], + "@huggingface/inference": ["@huggingface/inference@3.6.1", "", { "dependencies": { "@huggingface/jinja": "^0.3.3", "@huggingface/tasks": "^0.17.8" } }, "sha512-EtQlbBqcZycPe+qiTEFI+wNHOMpG0gwNTaZSvYu1juN1p/1dEgqAb2GO31dxLgNev2PzH9d+9nm8GngOsIepJg=="], "@huggingface/jinja": ["@huggingface/jinja@0.3.3", "", {}, "sha512-vQQr2JyWvVFba3Lj9es4q9vCl1sAc74fdgnEMoX8qHrXtswap9ge9uO3ONDzQB0cQ0PUyaKY2N6HaVbTBvSXvw=="], - "@huggingface/tasks": ["@huggingface/tasks@0.17.4", "", {}, "sha512-LES7+OosthFKdqRL0e+bA2d4jfKmiQWuqahsPrv0+EsSZtdHdaZ3nje0f2g5wq4miHX4xWpBLuWJknjdnBwXsA=="], + "@huggingface/tasks": ["@huggingface/tasks@0.17.8", "", {}, "sha512-8x9YxT1bkOhD0eMn7aytia4OrKQsjVTuQBg2Pkh7Sgjghv+8c6KQq4A5/dJbyNFdvY/1lcd2Si7NsUMhLufzCQ=="], "@huggingface/transformers": ["@huggingface/transformers@3.4.0", "", { "dependencies": { "@huggingface/jinja": "^0.3.3", "onnxruntime-node": "1.20.1", "onnxruntime-web": "1.22.0-dev.20250306-ccf8fdd9ea", "sharp": "^0.33.5" } }, "sha512-jyuglsWc+Ls9/U7eGDDY+xYgDgDtwxQ4ul/5VQoqo2r0LfAnJ+zSRUjKnY6paOyzyhbKaftfEsvXJ049aL1cyw=="], @@ -1588,7 +1624,7 @@ "@octokit/auth-oauth-app": ["@octokit/auth-oauth-app@8.1.3", "", { "dependencies": { "@octokit/auth-oauth-device": "^7.1.3", "@octokit/auth-oauth-user": "^5.1.3", "@octokit/request": "^9.2.1", "@octokit/types": "^13.6.2", "universal-user-agent": "^7.0.0" } }, "sha512-4e6OjVe5rZ8yBe8w7byBjpKtSXFuro7gqeGAAZc7QYltOF8wB93rJl2FE0a4U1Mt88xxPv/mS+25/0DuLk0Ewg=="], - "@octokit/auth-oauth-device": ["@octokit/auth-oauth-device@7.1.3", "", { "dependencies": { "@octokit/oauth-methods": "^5.1.4", "@octokit/request": "^9.2.1", "@octokit/types": "^13.6.2", "universal-user-agent": "^7.0.0" } }, "sha512-BECO/N4B/Uikj0w3GCvjf/odMujtYTP3q82BJSjxC2J3rxTEiZIJ+z2xnRlDb0IE9dQSaTgRqUPVOieSbFcVzg=="], + "@octokit/auth-oauth-device": ["@octokit/auth-oauth-device@7.1.4", "", { "dependencies": { "@octokit/oauth-methods": "^5.1.4", "@octokit/request": "^9.2.1", "@octokit/types": "^13.6.2", "universal-user-agent": "^7.0.0" } }, "sha512-yK35I9VGDGjYxu0NPZ9Rl+zXM/+DO/Hu1VR5FUNz+ZsU6i8B8oQ43TPwci9nuH8bAF6rQrKDNR9F0r0+kzYJhA=="], "@octokit/auth-oauth-user": ["@octokit/auth-oauth-user@5.1.3", "", { "dependencies": { "@octokit/auth-oauth-device": "^7.1.3", "@octokit/oauth-methods": "^5.1.3", "@octokit/request": "^9.2.1", "@octokit/types": "^13.6.2", "universal-user-agent": "^7.0.0" } }, "sha512-zNPByPn9K7TC+OOHKGxU+MxrE9SZAN11UHYEFLsK2NRn3akJN2LHRl85q+Eypr3tuB2GrKx3rfj2phJdkYCvzw=="], @@ -1608,23 +1644,23 @@ "@octokit/oauth-methods": ["@octokit/oauth-methods@5.1.4", "", { "dependencies": { "@octokit/oauth-authorization-url": "^7.0.0", "@octokit/request": "^9.2.1", "@octokit/request-error": "^6.1.7", "@octokit/types": "^13.6.2" } }, "sha512-Jc/ycnePClOvO1WL7tlC+TRxOFtyJBGuTDsL4dzXNiVZvzZdrPuNw7zHI3qJSUX2n6RLXE5L0SkFmYyNaVUFoQ=="], - "@octokit/openapi-types": ["@octokit/openapi-types@23.0.1", "", {}, "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g=="], + "@octokit/openapi-types": ["@octokit/openapi-types@24.2.0", "", {}, "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="], - "@octokit/openapi-webhooks-types": ["@octokit/openapi-webhooks-types@10.1.1", "", {}, "sha512-qBfqQVIDQaCFeGCofXieJDwvXcGgDn17+UwZ6WW6lfEvGYGreLFzTiaz9xjet9Us4zDf8iasoW3ixUj/R5lMhA=="], + "@octokit/openapi-webhooks-types": ["@octokit/openapi-webhooks-types@10.3.0", "", {}, "sha512-Dog+FB4pvsfcGZ9CFyYwb7I6K4QkzCDuN0H3hh5Nr9mMQ4wbBceqUKyJNKN2A0SQ6j4UU3CYNuvfoX9mQlhLUQ=="], "@octokit/plugin-enterprise-rest": ["@octokit/plugin-enterprise-rest@6.0.1", "", {}, "sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw=="], "@octokit/plugin-paginate-graphql": ["@octokit/plugin-paginate-graphql@5.2.4", "", { "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-pLZES1jWaOynXKHOqdnwZ5ULeVR6tVVCMm+AUbp0htdcyXDU95WbkYdU4R2ej1wKj5Tu94Mee2Ne0PjPO9cCyA=="], - "@octokit/plugin-paginate-rest": ["@octokit/plugin-paginate-rest@11.4.3", "", { "dependencies": { "@octokit/types": "^13.7.0" }, "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-tBXaAbXkqVJlRoA/zQVe9mUdb8rScmivqtpv3ovsC5xhje/a+NOCivs7eUhWBwCApJVsR4G5HMeaLbq7PxqZGA=="], + "@octokit/plugin-paginate-rest": ["@octokit/plugin-paginate-rest@11.6.0", "", { "dependencies": { "@octokit/types": "^13.10.0" }, "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw=="], "@octokit/plugin-request-log": ["@octokit/plugin-request-log@5.3.1", "", { "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw=="], - "@octokit/plugin-rest-endpoint-methods": ["@octokit/plugin-rest-endpoint-methods@13.3.1", "", { "dependencies": { "@octokit/types": "^13.8.0" }, "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-o8uOBdsyR+WR8MK9Cco8dCgvG13H1RlM1nWnK/W7TEACQBFux/vPREgKucxUfuDQ5yi1T3hGf4C5ZmZXAERgwQ=="], + "@octokit/plugin-rest-endpoint-methods": ["@octokit/plugin-rest-endpoint-methods@13.5.0", "", { "dependencies": { "@octokit/types": "^13.10.0" }, "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw=="], - "@octokit/plugin-retry": ["@octokit/plugin-retry@7.1.4", "", { "dependencies": { "@octokit/request-error": "^6.1.7", "@octokit/types": "^13.6.2", "bottleneck": "^2.15.3" }, "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-7AIP4p9TttKN7ctygG4BtR7rrB0anZqoU9ThXFk8nETqIfvgPUANTSYHqWYknK7W3isw59LpZeLI8pcEwiJdRg=="], + "@octokit/plugin-retry": ["@octokit/plugin-retry@7.2.0", "", { "dependencies": { "@octokit/request-error": "^6.1.7", "@octokit/types": "^13.6.2", "bottleneck": "^2.15.3" }, "peerDependencies": { "@octokit/core": ">=6" } }, "sha512-psMbEYb/Fh+V+ZaFo8J16QiFz4sVTv3GntCSU+hYqzHiMdc3P+hhHLVv+dJt0PGIPAGoIA5u+J2DCJdK6lEPsQ=="], - "@octokit/plugin-throttling": ["@octokit/plugin-throttling@9.4.0", "", { "dependencies": { "@octokit/types": "^13.7.0", "bottleneck": "^2.15.3" }, "peerDependencies": { "@octokit/core": "^6.1.3" } }, "sha512-IOlXxXhZA4Z3m0EEYtrrACkuHiArHLZ3CvqWwOez/pURNqRuwfoFlTPbN5Muf28pzFuztxPyiUiNwz8KctdZaQ=="], + "@octokit/plugin-throttling": ["@octokit/plugin-throttling@9.6.0", "", { "dependencies": { "@octokit/types": "^13.7.0", "bottleneck": "^2.15.3" }, "peerDependencies": { "@octokit/core": "^6.1.3" } }, "sha512-zn7m1N3vpJDaVzLqjCRdJ0cRzNiekHEWPi8Ww9xyPNrDt5PStHvVE0eR8wy4RSU8Eg7YO8MHyvn6sv25EGVhhg=="], "@octokit/request": ["@octokit/request@9.2.2", "", { "dependencies": { "@octokit/endpoint": "^10.1.3", "@octokit/request-error": "^6.1.7", "@octokit/types": "^13.6.2", "fast-content-type-parse": "^2.0.0", "universal-user-agent": "^7.0.2" } }, "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg=="], @@ -1634,9 +1670,9 @@ "@octokit/tsconfig": ["@octokit/tsconfig@1.0.2", "", {}, "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA=="], - "@octokit/types": ["@octokit/types@13.8.0", "", { "dependencies": { "@octokit/openapi-types": "^23.0.1" } }, "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A=="], + "@octokit/types": ["@octokit/types@13.10.0", "", { "dependencies": { "@octokit/openapi-types": "^24.2.0" } }, "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA=="], - "@octokit/webhooks": ["@octokit/webhooks@13.7.4", "", { "dependencies": { "@octokit/openapi-webhooks-types": "10.1.1", "@octokit/request-error": "^6.1.7", "@octokit/webhooks-methods": "^5.1.1" } }, "sha512-f386XyLTieQbgKPKS6ZMlH4dq8eLsxNddwofiKRZCq0bZ2gikoFwMD99K6l1oAwqe/KZNzrEziGicRgnzplplQ=="], + "@octokit/webhooks": ["@octokit/webhooks@13.7.5", "", { "dependencies": { "@octokit/openapi-webhooks-types": "10.3.0", "@octokit/request-error": "^6.1.7", "@octokit/webhooks-methods": "^5.1.1" } }, "sha512-qmmu4cfKmm58RWyDPUDoI7ls9JWw88qbqPzEi+TDBaSirHQPsixxdPU4OjPDcnDnjee7JXv525yv4qNN3BRlyg=="], "@octokit/webhooks-methods": ["@octokit/webhooks-methods@5.1.1", "", {}, "sha512-NGlEHZDseJTCj8TMMFehzwa9g7On4KJMPVHDSrHxCQumL6uSQR8wIkP/qesv52fXqV1BPf4pTxwtS31ldAt9Xg=="], @@ -1756,6 +1792,8 @@ "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg=="], + "@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-menu": "2.1.6", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-controllable-state": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA=="], + "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg=="], "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA=="], @@ -1764,6 +1802,8 @@ "@radix-ui/react-label": ["@radix-ui/react-label@2.1.2", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-zo1uGMTaNlHehDyFQcDZXRJhUPDuukcnHz0/jnrup0JA6qL+AFpAnty+7VKa9esuU5xTblAZzTGYJKSKaBxBhw=="], + "@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-collection": "1.1.2", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-direction": "1.1.0", "@radix-ui/react-dismissable-layer": "1.1.5", "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.2", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-popper": "1.2.2", "@radix-ui/react-portal": "1.1.4", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-roving-focus": "1.1.2", "@radix-ui/react-slot": "1.1.2", "@radix-ui/react-use-callback-ref": "1.1.0", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tBBb5CXDJW3t2mo9WlO7r6GTmWV0F0uzHZVFmlRmYpiSK1CDU5IKojP1pm7oknpBOrFZx/YgBRW9oorPO2S/Lg=="], + "@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.2", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.2", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0", "@radix-ui/react-use-rect": "1.1.0", "@radix-ui/react-use-size": "1.1.0", "@radix-ui/rect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA=="], "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.4", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA=="], @@ -1822,7 +1862,7 @@ "@redocly/config": ["@redocly/config@0.22.1", "", {}, "sha512-1CqQfiG456v9ZgYBG9xRQHnpXjt8WoSnDwdkX6gxktuK69v2037hTAR1eh0DGIqpZ1p4k82cGH8yTNwt7/pI9g=="], - "@redocly/openapi-core": ["@redocly/openapi-core@1.33.1", "", { "dependencies": { "@redocly/ajv": "^8.11.2", "@redocly/config": "^0.22.0", "colorette": "^1.2.0", "https-proxy-agent": "^7.0.5", "js-levenshtein": "^1.1.6", "js-yaml": "^4.1.0", "minimatch": "^5.0.1", "pluralize": "^8.0.0", "yaml-ast-parser": "0.0.43" } }, "sha512-tL3v8FVwdcCAcruOZV77uxH2ZFtnY3DRPG+rgmlm9hsu5uoatofVSJIJHUroz54KJ8ryeo28wQHhOr8iReGGEQ=="], + "@redocly/openapi-core": ["@redocly/openapi-core@1.34.0", "", { "dependencies": { "@redocly/ajv": "^8.11.2", "@redocly/config": "^0.22.0", "colorette": "^1.2.0", "https-proxy-agent": "^7.0.5", "js-levenshtein": "^1.1.6", "js-yaml": "^4.1.0", "minimatch": "^5.0.1", "pluralize": "^8.0.0", "yaml-ast-parser": "0.0.43" } }, "sha512-Ji00EiLQRXq0pJIz5pAjGF9MfQvQVsQehc6uIis6sqat8tG/zh25Zi64w6HVGEDgJEzUeq/CuUlD0emu3Hdaqw=="], "@reduxjs/toolkit": ["@reduxjs/toolkit@1.9.7", "", { "dependencies": { "immer": "^9.0.21", "redux": "^4.2.1", "redux-thunk": "^2.4.2", "reselect": "^4.1.8" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18", "react-redux": "^7.2.1 || ^8.0.2" }, "optionalPeers": ["react", "react-redux"] }, "sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ=="], @@ -1868,43 +1908,43 @@ "@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.35.0", "", { "os": "android", "cpu": "arm" }, "sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.36.0", "", { "os": "android", "cpu": "arm" }, "sha512-jgrXjjcEwN6XpZXL0HUeOVGfjXhPyxAbbhD0BlXUB+abTOpbPiN5Wb3kOT7yb+uEtATNYF5x5gIfwutmuBA26w=="], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.35.0", "", { "os": "android", "cpu": "arm64" }, "sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA=="], + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.36.0", "", { "os": "android", "cpu": "arm64" }, "sha512-NyfuLvdPdNUfUNeYKUwPwKsE5SXa2J6bCt2LdB/N+AxShnkpiczi3tcLJrm5mA+eqpy0HmaIY9F6XCa32N5yzg=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.35.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.36.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JQ1Jk5G4bGrD4pWJQzWsD8I1n1mgPXq33+/vP4sk8j/z/C2siRuxZtaUA7yMTf71TCZTZl/4e1bfzwUmFb3+rw=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.35.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.36.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-6c6wMZa1lrtiRsbDziCmjE53YbTkxMYhhnWnSW8R/yqsM7a6mSJ3uAVT0t8Y/DGt7gxUWYuFM4bwWk9XCJrFKA=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.35.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.36.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-KXVsijKeJXOl8QzXTsA+sHVDsFOmMCdBRgFmBb+mfEb/7geR7+C8ypAml4fquUt14ZyVXaw2o1FWhqAfOvA4sg=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.35.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.36.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dVeWq1ebbvByI+ndz4IJcD4a09RJgRYmLccwlQ8bPd4olz3Y213uf1iwvc7ZaxNn2ab7bjc08PrtBgMu6nb4pQ=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.35.0", "", { "os": "linux", "cpu": "arm" }, "sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.36.0", "", { "os": "linux", "cpu": "arm" }, "sha512-bvXVU42mOVcF4le6XSjscdXjqx8okv4n5vmwgzcmtvFdifQ5U4dXFYaCB87namDRKlUL9ybVtLQ9ztnawaSzvg=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.35.0", "", { "os": "linux", "cpu": "arm" }, "sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.36.0", "", { "os": "linux", "cpu": "arm" }, "sha512-JFIQrDJYrxOnyDQGYkqnNBtjDwTgbasdbUiQvcU8JmGDfValfH1lNpng+4FWlhaVIR4KPkeddYjsVVbmJYvDcg=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.35.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.36.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-KqjYVh3oM1bj//5X7k79PSCZ6CvaVzb7Qs7VMWS+SlWB5M8p3FqufLP9VNp4CazJ0CsPDLwVD9r3vX7Ci4J56A=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.35.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.36.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-QiGnhScND+mAAtfHqeT+cB1S9yFnNQ/EwCg5yE3MzoaZZnIV0RV9O5alJAoJKX/sBONVKeZdMfO8QSaWEygMhw=="], - "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.35.0", "", { "os": "linux", "cpu": "none" }, "sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g=="], + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.36.0", "", { "os": "linux", "cpu": "none" }, "sha512-1ZPyEDWF8phd4FQtTzMh8FQwqzvIjLsl6/84gzUxnMNFBtExBtpL51H67mV9xipuxl1AEAerRBgBwFNpkw8+Lg=="], - "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.35.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA=="], + "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.36.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-VMPMEIUpPFKpPI9GZMhJrtu8rxnp6mJR3ZzQPykq4xc2GmdHj3Q4cA+7avMyegXy4n1v+Qynr9fR88BmyO74tg=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.35.0", "", { "os": "linux", "cpu": "none" }, "sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.36.0", "", { "os": "linux", "cpu": "none" }, "sha512-ttE6ayb/kHwNRJGYLpuAvB7SMtOeQnVXEIpMtAvx3kepFQeowVED0n1K9nAdraHUPJ5hydEMxBpIR7o4nrm8uA=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.35.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.36.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-4a5gf2jpS0AIe7uBjxDeUMNcFmaRTbNv7NxI5xOCs4lhzsVyGR/0qBXduPnoWf6dGC365saTiwag8hP1imTgag=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.35.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.36.0", "", { "os": "linux", "cpu": "x64" }, "sha512-5KtoW8UWmwFKQ96aQL3LlRXX16IMwyzMq/jSSVIIyAANiE1doaQsx/KRyhAvpHlPjPiSU/AYX/8m+lQ9VToxFQ=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.35.0", "", { "os": "linux", "cpu": "x64" }, "sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.36.0", "", { "os": "linux", "cpu": "x64" }, "sha512-sycrYZPrv2ag4OCvaN5js+f01eoZ2U+RmT5as8vhxiFz+kxwlHrsxOwKPSA8WyS+Wc6Epid9QeI/IkQ9NkgYyQ=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.35.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.36.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-qbqt4N7tokFwwSVlWDsjfoHgviS3n/vZ8LK0h1uLG9TYIRuUTJC88E1xb3LM2iqZ/WTqNQjYrtmtGmrmmawB6A=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.35.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw=="], + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.36.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-t+RY0JuRamIocMuQcfwYSOkmdX9dtkr1PbhKW42AMvaDQa+jOdpUYysroTF/nuPpAaQMWp7ye+ndlmmthieJrQ=="], - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.35.0", "", { "os": "win32", "cpu": "x64" }, "sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw=="], + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.36.0", "", { "os": "win32", "cpu": "x64" }, "sha512-aRXd7tRZkWLqGbChgcMMDEHjOKudo1kChb1Jt1IfR8cY/KIpgNviLeJy5FUb9IpSuQj8dU2fAYNMPW/hLKOSTw=="], "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="], @@ -1944,7 +1984,7 @@ "@sigstore/verify": ["@sigstore/verify@1.2.1", "", { "dependencies": { "@sigstore/bundle": "^2.3.2", "@sigstore/core": "^1.1.0", "@sigstore/protobuf-specs": "^0.3.2" } }, "sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g=="], - "@sinclair/typebox": ["@sinclair/typebox@0.32.35", "", {}, "sha512-Ul3YyOTU++to8cgNkttakC0dWvpERr6RYoHO2W47DLbFvrwBDJUY31B1sImH6JZSYc4Kt4PyHtoPNu+vL2r2dA=="], + "@sinclair/typebox": ["@sinclair/typebox@0.34.30", "", {}, "sha512-gFB3BiqjDxEoadW0zn+xyMVb7cLxPCoblVn2C/BKpI41WPYi2d6fwHAlynPNZ5O/Q4WEiujdnJzVtvG/Jc2CBQ=="], "@sindresorhus/is": ["@sindresorhus/is@4.6.0", "", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="], @@ -2078,7 +2118,7 @@ "@solana/spl-token-metadata": ["@solana/spl-token-metadata@0.1.6", "", { "dependencies": { "@solana/codecs": "2.0.0-rc.1" }, "peerDependencies": { "@solana/web3.js": "^1.95.3" } }, "sha512-7sMt1rsm/zQOQcUWllQX9mD2O6KhSAtY1hFR2hfFwgqfFWzSY9E9GDvFVNYUI1F0iQKcm6HmePU9QbKRXTEBiA=="], - "@solana/wallet-adapter-base": ["@solana/wallet-adapter-base@0.9.23", "", { "dependencies": { "@solana/wallet-standard-features": "^1.1.0", "@wallet-standard/base": "^1.0.1", "@wallet-standard/features": "^1.0.3", "eventemitter3": "^4.0.7" }, "peerDependencies": { "@solana/web3.js": "^1.77.3" } }, "sha512-apqMuYwFp1jFi55NxDfvXUX2x1T0Zh07MxhZ/nCCTGys5raSfYUh82zen2BLv8BSDj/JxZ2P/s7jrQZGrX8uAw=="], + "@solana/wallet-adapter-base": ["@solana/wallet-adapter-base@0.9.24", "", { "dependencies": { "@solana/wallet-standard-features": "^1.1.0", "@wallet-standard/base": "^1.0.1", "@wallet-standard/features": "^1.0.3", "eventemitter3": "^4.0.7" }, "peerDependencies": { "@solana/web3.js": "^1.77.3" } }, "sha512-f3kwHF/2Lx3YgcO37B45MM46YLFy4QkdLemZ+N/0SwLAnSfhq3+Vb9bC5vuoupMJ/onos09TIDeIxRdg/+51kw=="], "@solana/wallet-standard-features": ["@solana/wallet-standard-features@1.3.0", "", { "dependencies": { "@wallet-standard/base": "^1.1.0", "@wallet-standard/features": "^1.1.0" } }, "sha512-ZhpZtD+4VArf6RPitsVExvgkF+nGghd1rzPjd97GmBximpnt1rsUxMOEyoIEuH3XBxPyNB6Us7ha7RHWQR+abg=="], @@ -2112,27 +2152,27 @@ "@svgr/webpack": ["@svgr/webpack@8.1.0", "", { "dependencies": { "@babel/core": "^7.21.3", "@babel/plugin-transform-react-constant-elements": "^7.21.3", "@babel/preset-env": "^7.20.2", "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.21.0", "@svgr/core": "8.1.0", "@svgr/plugin-jsx": "8.1.0", "@svgr/plugin-svgo": "8.1.0" } }, "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA=="], - "@swc/core": ["@swc/core@1.11.9", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.19" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.11.9", "@swc/core-darwin-x64": "1.11.9", "@swc/core-linux-arm-gnueabihf": "1.11.9", "@swc/core-linux-arm64-gnu": "1.11.9", "@swc/core-linux-arm64-musl": "1.11.9", "@swc/core-linux-x64-gnu": "1.11.9", "@swc/core-linux-x64-musl": "1.11.9", "@swc/core-win32-arm64-msvc": "1.11.9", "@swc/core-win32-ia32-msvc": "1.11.9", "@swc/core-win32-x64-msvc": "1.11.9" }, "peerDependencies": { "@swc/helpers": "*" }, "optionalPeers": ["@swc/helpers"] }, "sha512-4UQ66FwTkFDr+UzYzRNKQyHMScOrc4zJbTJHyK6dP1yVMrxi5sl0FTzNKiqoYvRZ7j8TAYgtYvvuPSW/XXvp5g=="], + "@swc/core": ["@swc/core@1.11.11", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.19" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.11.11", "@swc/core-darwin-x64": "1.11.11", "@swc/core-linux-arm-gnueabihf": "1.11.11", "@swc/core-linux-arm64-gnu": "1.11.11", "@swc/core-linux-arm64-musl": "1.11.11", "@swc/core-linux-x64-gnu": "1.11.11", "@swc/core-linux-x64-musl": "1.11.11", "@swc/core-win32-arm64-msvc": "1.11.11", "@swc/core-win32-ia32-msvc": "1.11.11", "@swc/core-win32-x64-msvc": "1.11.11" }, "peerDependencies": { "@swc/helpers": "*" }, "optionalPeers": ["@swc/helpers"] }, "sha512-pCVY2Wn6dV/labNvssk9b3Owi4WOYsapcbWm90XkIj4xH/56Z6gzja9fsU+4MdPuEfC2Smw835nZHcdCFGyX6A=="], - "@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.11.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-moqbPCWG6SHiDMENTDYsEQJ0bFustbLtrdbDbdjnijSyhCyIcm9zKowmovE6MF8JBdOwmLxbuN1Yarq6CrPNlw=="], + "@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.11.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vJcjGVDB8cZH7zyOkC0AfpFYI/7GHKG0NSsH3tpuKrmoAXJyCYspKPGid7FT53EAlWreN7+Pew+bukYf5j+Fmg=="], - "@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.11.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-/lgMo5l9q6y3jjLM3v30y6SBvuuyLsM/K94hv3hPvDf91N+YlZLw4D7KY0Qknfhj6WytoAcjOIDU6xwBRPyUWg=="], + "@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.11.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-/N4dGdqEYvD48mCF3QBSycAbbQd3yoZ2YHSzYesQf8usNc2YpIhYqEH3sql02UsxTjEFOJSf1bxZABDdhbSl6A=="], - "@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.11.9", "", { "os": "linux", "cpu": "arm" }, "sha512-7bL6z/63If11IpBElQRozIGRadiy6rt3DoUyfGuFIFQKxtnZxzHuLxm1/wrCAGN9iAZxrpHxHP0VbPQvr6Mcjg=="], + "@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.11.11", "", { "os": "linux", "cpu": "arm" }, "sha512-hsBhKK+wVXdN3x9MrL5GW0yT8o9GxteE5zHAI2HJjRQel3HtW7m5Nvwaq+q8rwMf4YQRd8ydbvwl4iUOZx7i2Q=="], - "@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.11.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-9ArpxjrNbyFTr7gG+toiGbbK2mfS+X97GIruBKPsD8CJH/yJlMknBsX3lfy9h/L119zYVnFBmZDnwsv5yW8/cw=="], + "@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.11.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-YOCdxsqbnn/HMPCNM6nrXUpSndLXMUssGTtzT7ffXqr7WuzRg2e170FVDVQFIkb08E7Ku5uOnnUVAChAJQbMOQ=="], - "@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.11.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-UOnunJWu7T7oNkBr4DLMwXXbldjiwi+JxmqBKrD2+BNiHGu6P5VpqDHiTGuWuLrda0TcTmeNE6gzlIVOVBo/vw=="], + "@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.11.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-nR2tfdQRRzwqR2XYw9NnBk9Fdvff/b8IiJzDL28gRR2QiJWLaE8LsRovtWrzCOYq6o5Uu9cJ3WbabWthLo4jLw=="], - "@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.11.9", "", { "os": "linux", "cpu": "x64" }, "sha512-HAqmCkNoNhRusBqSokyylXKsLJ/dr3dnMgBERdUrCIh47L8CKR2qEFUP6FI05sHVB85403ctWnfzBYblcarpqg=="], + "@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.11.11", "", { "os": "linux", "cpu": "x64" }, "sha512-b4gBp5HA9xNWNC5gsYbdzGBJWx4vKSGybGMGOVWWuF+ynx10+0sA/o4XJGuNHm8TEDuNh9YLKf6QkIO8+GPJ1g=="], - "@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.11.9", "", { "os": "linux", "cpu": "x64" }, "sha512-THwUT2g2qSWUxhi3NGRCEdmh/q7WKl3d5jcN9mz/4jum76Tb46LB9p3oOVPBIcfnFQ9OaddExjCwLoUl0ju2pA=="], + "@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.11.11", "", { "os": "linux", "cpu": "x64" }, "sha512-dEvqmQVswjNvMBwXNb8q5uSvhWrJLdttBSef3s6UC5oDSwOr00t3RQPzyS3n5qmGJ8UMTdPRmsopxmqaODISdg=="], - "@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.11.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-r4SGD9lR0MM9HSIsQ72BEL3Za3XsuVj+govuXQTlK0mty5gih4L+Qgfnb9PmhjFakK3F63gZyyEr2y8Fj0mN6Q=="], + "@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.11.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-aZNZznem9WRnw2FbTqVpnclvl8Q2apOBW2B316gZK+qxbe+ktjOUnYaMhdCG3+BYggyIBDOnaJeQrXbKIMmNdw=="], - "@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.11.9", "", { "os": "win32", "cpu": "ia32" }, "sha512-jrEh6MDSnhwfpjRlSWd2Bk8pS5EjreQD1YbkNcnXviQf3+H0wSPmeVSktZyoIdkxAuc2suFx8mj7Yja2UXAgUg=="], + "@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.11.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-DjeJn/IfjgOddmJ8IBbWuDK53Fqw7UvOz7kyI/728CSdDYC3LXigzj3ZYs4VvyeOt+ZcQZUB2HA27edOifomGw=="], - "@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.11.9", "", { "os": "win32", "cpu": "x64" }, "sha512-oAwuhzr+1Bmb4As2wa3k57/WPJeyVEYRQelwEMYjPgi/h6TH+Y69jQAgKOd+ec1Yl8L5nkWTZMVA/dKDac1bAQ=="], + "@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.11.11", "", { "os": "win32", "cpu": "x64" }, "sha512-Gp/SLoeMtsU4n0uRoKDOlGrRC6wCfifq7bqLwSlAG8u8MyJYJCcwjg7ggm0rhLdC2vbiZ+lLVl3kkETp+JUvKg=="], "@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="], @@ -2142,9 +2182,9 @@ "@szmarczak/http-timer": ["@szmarczak/http-timer@5.0.1", "", { "dependencies": { "defer-to-connect": "^2.0.1" } }, "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw=="], - "@tanstack/query-core": ["@tanstack/query-core@5.68.0", "", {}, "sha512-r8rFYYo8/sY/LNaOqX84h12w7EQev4abFXDWy4UoDVUJzJ5d9Fbmb8ayTi7ScG+V0ap44SF3vNs/45mkzDGyGw=="], + "@tanstack/query-core": ["@tanstack/query-core@5.69.0", "", {}, "sha512-Kn410jq6vs1P8Nm+ZsRj9H+U3C0kjuEkYLxbiCyn3MDEiYor1j2DGVULqAz62SLZtUZ/e9Xt6xMXiJ3NJ65WyQ=="], - "@tanstack/react-query": ["@tanstack/react-query@5.68.0", "", { "dependencies": { "@tanstack/query-core": "5.68.0" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-mMOdGDKlwTP/WV72QqSNf4PAMeoBp/DqBHQ222wBfb51Looi8QUqnCnb9O98ZgvNISmy6fzxRGBJdZ+9IBvX2Q=="], + "@tanstack/react-query": ["@tanstack/react-query@5.69.0", "", { "dependencies": { "@tanstack/query-core": "5.69.0" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-Ift3IUNQqTcaFa1AiIQ7WCb/PPy8aexZdq9pZWLXhfLcLxH0+PZqJ2xFImxCpdDZrFRZhLJrh76geevS5xjRhA=="], "@tauri-apps/api": ["@tauri-apps/api@2.3.0", "", {}, "sha512-33Z+0lX2wgZbx1SPFfqvzI6su63hCBkbzv+5NexeYjIx7WA9htdOKoRR7Dh3dJyltqS5/J8vQFyybiRoaL0hlA=="], @@ -2378,7 +2418,7 @@ "@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="], - "@types/react": ["@types/react@19.0.10", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g=="], + "@types/react": ["@types/react@19.0.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA=="], "@types/react-dom": ["@types/react-dom@19.0.4", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg=="], @@ -2436,31 +2476,31 @@ "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], - "@unrs/rspack-resolver-binding-darwin-arm64": ["@unrs/rspack-resolver-binding-darwin-arm64@1.1.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bQx2L40UF5XxsXwkD26PzuspqUbUswWVbmclmUC+c83Cv/EFrFJ1JaZj5Q5jyYglKGOtyIWY/hXTCdWRN9vT0Q=="], + "@unrs/rspack-resolver-binding-darwin-arm64": ["@unrs/rspack-resolver-binding-darwin-arm64@1.2.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-i7z0B+C0P8Q63O/5PXJAzeFtA1ttY3OR2VSJgGv18S+PFNwD98xHgAgPOT1H5HIV6jlQP8Avzbp09qxJUdpPNw=="], - "@unrs/rspack-resolver-binding-darwin-x64": ["@unrs/rspack-resolver-binding-darwin-x64@1.1.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-dMi9a7//BsuPTnhWEDxmdKZ6wxQlPnAob8VSjefGbKX/a+pHfTaX1pm/jv2VPdarP96IIjCKPatJS/TtLQeGQA=="], + "@unrs/rspack-resolver-binding-darwin-x64": ["@unrs/rspack-resolver-binding-darwin-x64@1.2.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-YEdFzPjIbDUCfmehC6eS+AdJYtFWY35YYgWUnqqTM2oe/N58GhNy5yRllxYhxwJ9GcfHoNc6Ubze1yjkNv+9Qg=="], - "@unrs/rspack-resolver-binding-freebsd-x64": ["@unrs/rspack-resolver-binding-freebsd-x64@1.1.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-RiBZQ+LSORQObfhV1yH7jGz+4sN3SDYtV53jgc8tUVvqdqVDaUm1KA3zHLffmoiYNGrYkE3sSreGC+FVpsB4Vg=="], + "@unrs/rspack-resolver-binding-freebsd-x64": ["@unrs/rspack-resolver-binding-freebsd-x64@1.2.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TU4ntNXDgPN2giQyyzSnGWf/dVCem5lvwxg0XYvsvz35h5H19WrhTmHgbrULMuypCB3aHe1enYUC9rPLDw45mA=="], - "@unrs/rspack-resolver-binding-linux-arm-gnueabihf": ["@unrs/rspack-resolver-binding-linux-arm-gnueabihf@1.1.2", "", { "os": "linux", "cpu": "arm" }, "sha512-IyKIFBtOvuPCJt1WPx9e9ovTGhZzrIbW11vWzw4aPmx3VShE+YcMpAldqQubdCep0UVKZyFt+2hQDQZwFiJ4jg=="], + "@unrs/rspack-resolver-binding-linux-arm-gnueabihf": ["@unrs/rspack-resolver-binding-linux-arm-gnueabihf@1.2.2", "", { "os": "linux", "cpu": "arm" }, "sha512-ik3w4/rU6RujBvNWiDnKdXi1smBhqxEDhccNi/j2rHaMjm0Fk49KkJ6XKsoUnD2kZ5xaMJf9JjailW/okfUPIw=="], - "@unrs/rspack-resolver-binding-linux-arm64-gnu": ["@unrs/rspack-resolver-binding-linux-arm64-gnu@1.1.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-RfYtlCtJrv5i6TO4dSlpbyOJX9Zbhmkqrr9hjDfr6YyE5KD0ywLRzw8UjXsohxG1XWgRpb2tvPuRYtURJwbqWg=="], + "@unrs/rspack-resolver-binding-linux-arm64-gnu": ["@unrs/rspack-resolver-binding-linux-arm64-gnu@1.2.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-fp4Azi8kHz6TX8SFmKfyScZrMLfp++uRm2srpqRjsRZIIBzH74NtSkdEUHImR4G7f7XJ+sVZjCc6KDDK04YEpQ=="], - "@unrs/rspack-resolver-binding-linux-arm64-musl": ["@unrs/rspack-resolver-binding-linux-arm64-musl@1.1.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-MaITzkoqsn1Rm3+YnplubgAQEfOt+2jHfFvuFhXseUfcfbxe8Zyc3TM7LKwgv7mRVjIl+/yYN5JqL0cjbnhAnQ=="], + "@unrs/rspack-resolver-binding-linux-arm64-musl": ["@unrs/rspack-resolver-binding-linux-arm64-musl@1.2.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-gMiG3DCFioJxdGBzhlL86KcFgt9HGz0iDhw0YVYPsShItpN5pqIkNrI+L/Q/0gfDiGrfcE0X3VANSYIPmqEAlQ=="], - "@unrs/rspack-resolver-binding-linux-x64-gnu": ["@unrs/rspack-resolver-binding-linux-x64-gnu@1.1.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Nu981XmzQqis/uB3j4Gi3p5BYCd/zReU5zbJmjMrEH7IIRH0dxZpdOmS/+KwEk6ao7Xd8P2D2gDHpHD/QTp0aQ=="], + "@unrs/rspack-resolver-binding-linux-x64-gnu": ["@unrs/rspack-resolver-binding-linux-x64-gnu@1.2.2", "", { "os": "linux", "cpu": "x64" }, "sha512-n/4n2CxaUF9tcaJxEaZm+lqvaw2gflfWQ1R9I7WQgYkKEKbRKbpG/R3hopYdUmLSRI4xaW1Cy0Bz40eS2Yi4Sw=="], - "@unrs/rspack-resolver-binding-linux-x64-musl": ["@unrs/rspack-resolver-binding-linux-x64-musl@1.1.2", "", { "os": "linux", "cpu": "x64" }, "sha512-xJupeDvaRpV0ADMuG1dY9jkOjhUzTqtykvchiU2NldSD+nafSUcMWnoqzNUx7HGiqbTMOw9d9xT8ZiFs+6ZFyQ=="], + "@unrs/rspack-resolver-binding-linux-x64-musl": ["@unrs/rspack-resolver-binding-linux-x64-musl@1.2.2", "", { "os": "linux", "cpu": "x64" }, "sha512-cHyhAr6rlYYbon1L2Ag449YCj3p6XMfcYTP0AQX+KkQo025d1y/VFtPWvjMhuEsE2lLvtHm7GdJozj6BOMtzVg=="], - "@unrs/rspack-resolver-binding-wasm32-wasi": ["@unrs/rspack-resolver-binding-wasm32-wasi@1.1.2", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.7" }, "cpu": "none" }, "sha512-un6X/xInks+KEgGpIHFV8BdoODHRohaDRvOwtjq+FXuoI4Ga0P6sLRvf4rPSZDvoMnqUhZtVNG0jG9oxOnrrLQ=="], + "@unrs/rspack-resolver-binding-wasm32-wasi": ["@unrs/rspack-resolver-binding-wasm32-wasi@1.2.2", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.7" }, "cpu": "none" }, "sha512-eogDKuICghDLGc32FtP+WniG38IB1RcGOGz0G3z8406dUdjJvxfHGuGs/dSlM9YEp/v0lEqhJ4mBu6X2nL9pog=="], - "@unrs/rspack-resolver-binding-win32-arm64-msvc": ["@unrs/rspack-resolver-binding-win32-arm64-msvc@1.1.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-2lCFkeT1HYUb/OOStBS1m67aZOf9BQxRA+Wf/xs94CGgzmoQt7H4V/BrkB/GSGKsudXjkiwt2oHNkHiowAS90A=="], + "@unrs/rspack-resolver-binding-win32-arm64-msvc": ["@unrs/rspack-resolver-binding-win32-arm64-msvc@1.2.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-7sWRJumhpXSi2lccX8aQpfFXHsSVASdWndLv8AmD8nDRA/5PBi8IplQVZNx2mYRx6+Bp91Z00kuVqpXO9NfCTg=="], - "@unrs/rspack-resolver-binding-win32-x64-msvc": ["@unrs/rspack-resolver-binding-win32-x64-msvc@1.1.2", "", { "os": "win32", "cpu": "x64" }, "sha512-EYfya5HCQ/8Yfy7rvAAX2rGytu81+d/CIhNCbZfNKLQ690/qFsdEeTXRsMQW1afHoluMM50PsjPYu8ndy8fSQg=="], + "@unrs/rspack-resolver-binding-win32-x64-msvc": ["@unrs/rspack-resolver-binding-win32-x64-msvc@1.2.2", "", { "os": "win32", "cpu": "x64" }, "sha512-hewo/UMGP1a7O6FG/ThcPzSJdm/WwrYDNkdGgWl6M18H6K6MSitklomWpT9MUtT5KGj++QJb06va/14QBC4pvw=="], "@vitejs/plugin-react": ["@vitejs/plugin-react@4.3.4", "", { "dependencies": { "@babel/core": "^7.26.0", "@babel/plugin-transform-react-jsx-self": "^7.25.9", "@babel/plugin-transform-react-jsx-source": "^7.25.9", "@types/babel__core": "^7.20.5", "react-refresh": "^0.14.2" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" } }, "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug=="], - "@vitejs/plugin-react-swc": ["@vitejs/plugin-react-swc@3.8.0", "", { "dependencies": { "@swc/core": "^1.10.15" }, "peerDependencies": { "vite": "^4 || ^5 || ^6" } }, "sha512-T4sHPvS+DIqDP51ifPqa9XIRAz/kIvIi8oXcnOZZgHmMotgmmdxe/DD5tMFlt5nuIRzT0/QuiwmKlH0503Aapw=="], + "@vitejs/plugin-react-swc": ["@vitejs/plugin-react-swc@3.8.1", "", { "dependencies": { "@swc/core": "^1.11.11" }, "peerDependencies": { "vite": "^4 || ^5 || ^6" } }, "sha512-aEUPCckHDcFyxpwFm0AIkbtv6PpUp3xTb9wYGFjtABynXjCYKkWoxX0AOK9NT9XCrdk6mBBUOeHQS+RKdcNO1A=="], "@vitest/coverage-v8": ["@vitest/coverage-v8@2.1.5", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", "debug": "^4.3.7", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", "magic-string": "^0.30.12", "magicast": "^0.3.5", "std-env": "^3.8.0", "test-exclude": "^7.0.1", "tinyrainbow": "^1.2.0" }, "peerDependencies": { "@vitest/browser": "2.1.5", "vitest": "2.1.5" }, "optionalPeers": ["@vitest/browser"] }, "sha512-/RoopB7XGW7UEkUndRXF87A9CwkoZAJW01pj8/3pgmDVsjMH2IKy6H1A38po9tmUlwhSyYs0az82rbKd9Yaynw=="], @@ -2470,7 +2510,7 @@ "@vitest/mocker": ["@vitest/mocker@3.0.5", "", { "dependencies": { "@vitest/spy": "3.0.5", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw=="], - "@vitest/pretty-format": ["@vitest/pretty-format@3.0.8", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg=="], + "@vitest/pretty-format": ["@vitest/pretty-format@3.0.9", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA=="], "@vitest/runner": ["@vitest/runner@3.0.5", "", { "dependencies": { "@vitest/utils": "3.0.5", "pathe": "^2.0.2" } }, "sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A=="], @@ -2552,7 +2592,7 @@ "aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="], - "ai": ["ai@4.1.61", "", { "dependencies": { "@ai-sdk/provider": "1.0.11", "@ai-sdk/provider-utils": "2.1.13", "@ai-sdk/react": "1.1.23", "@ai-sdk/ui-utils": "1.1.19", "@opentelemetry/api": "1.9.0", "eventsource-parser": "^3.0.0", "jsondiffpatch": "0.6.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.0.0" }, "optionalPeers": ["react", "zod"] }, "sha512-Y9SAyGJEeW23F6C7PSHZXYNEvbH2cqJm0rVW2AoeFaXFT13ttx8rAqs8wz2w466C1UB329yl5PXayFcHqofSEA=="], + "ai": ["ai@4.1.63", "", { "dependencies": { "@ai-sdk/provider": "1.0.12", "@ai-sdk/provider-utils": "2.1.14", "@ai-sdk/react": "1.1.24", "@ai-sdk/ui-utils": "1.1.20", "@opentelemetry/api": "1.9.0", "eventsource-parser": "^3.0.0", "jsondiffpatch": "0.6.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.0.0" }, "optionalPeers": ["react", "zod"] }, "sha512-XXAU/jbtNZOHkTh9ZO4+ttXFXRjcs/62jJHbpO2M8UiH2FVIDia4fy4D5l8jGKlYVzKeE7rx/qB2GtrMjcc07w=="], "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], @@ -2630,6 +2670,8 @@ "arrify": ["arrify@2.0.1", "", {}, "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="], + "asap": ["asap@2.0.6", "", {}, "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="], + "asn1": ["asn1@0.2.6", "", { "dependencies": { "safer-buffer": "~2.1.0" } }, "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ=="], "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], @@ -2660,7 +2702,7 @@ "axe-core": ["axe-core@4.10.3", "", {}, "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg=="], - "axios": ["axios@1.8.3", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A=="], + "axios": ["axios@1.8.4", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw=="], "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], @@ -2670,11 +2712,11 @@ "babel-plugin-dynamic-import-node": ["babel-plugin-dynamic-import-node@2.3.3", "", { "dependencies": { "object.assign": "^4.1.0" } }, "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ=="], - "babel-plugin-polyfill-corejs2": ["babel-plugin-polyfill-corejs2@0.4.12", "", { "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.3", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og=="], + "babel-plugin-polyfill-corejs2": ["babel-plugin-polyfill-corejs2@0.4.13", "", { "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.4", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g=="], "babel-plugin-polyfill-corejs3": ["babel-plugin-polyfill-corejs3@0.11.1", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.3", "core-js-compat": "^3.40.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ=="], - "babel-plugin-polyfill-regenerator": ["babel-plugin-polyfill-regenerator@0.6.3", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.3" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q=="], + "babel-plugin-polyfill-regenerator": ["babel-plugin-polyfill-regenerator@0.6.4", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.4" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw=="], "bail": ["bail@1.0.5", "", {}, "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ=="], @@ -2708,8 +2750,6 @@ "before-after-hook": ["before-after-hook@3.0.2", "", {}, "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A=="], - "better-sqlite3": ["better-sqlite3@11.8.1", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-9BxNaBkblMjhJW8sMRZxnxVTRgbRmssZW0Oxc1MPBTfiR+WW21e2Mk4qu8CzrcZb1LwPCnFsfDEzq+SNcBU8eg=="], - "big.js": ["big.js@5.2.2", "", {}, "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="], "bigint-buffer": ["bigint-buffer@1.1.5", "", { "dependencies": { "bindings": "^1.3.0" } }, "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA=="], @@ -2722,7 +2762,7 @@ "binary-version": ["binary-version@7.1.0", "", { "dependencies": { "execa": "^8.0.1", "find-versions": "^6.0.0" } }, "sha512-Iy//vPc3ANPNlIWd242Npqc8MK0a/i4kVcHDlDA6HNMv5zMxz4ulIFhOSYJVKw/8AbHdHy0CnGYEt1QqSXxPsw=="], - "bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="], + "bindings": ["bindings@1.2.1", "", {}, "sha512-u4cBQNepWxYA55FunZSM7wMi55yQaN0otnhhilNoWHq0MfOfJeQx0v0mRRpolGOExPjZcl6FtB0BB8Xkb88F0g=="], "bip174": ["bip174@3.0.0-rc.1", "", { "dependencies": { "uint8array-tools": "^0.0.9", "varuint-bitcoin": "^2.0.0" } }, "sha512-+8P3BpSairVNF2Nee6Ksdc1etIjWjBOi/MH0MwKtq9YaYp+S2Hk2uvup0e8hCT4IKlS58nXJyyQVmW92zPoD4Q=="], @@ -2816,12 +2856,14 @@ "caniuse-api": ["caniuse-api@3.0.0", "", { "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", "lodash.memoize": "^4.1.2", "lodash.uniq": "^4.5.0" } }, "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw=="], - "caniuse-lite": ["caniuse-lite@1.0.30001705", "", {}, "sha512-S0uyMMiYvA7CxNgomYBwwwPUnWzFD83f3B1ce5jHUfHTH//QL6hHsreI8RVC5606R4ssqravelYO5TU6t8sEyg=="], + "caniuse-lite": ["caniuse-lite@1.0.30001706", "", {}, "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug=="], "canvas": ["canvas@2.11.2", "", { "dependencies": { "@mapbox/node-pre-gyp": "^1.0.0", "nan": "^2.17.0", "simple-get": "^3.0.3" } }, "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw=="], "capsolver-npm": ["capsolver-npm@2.0.2", "", { "dependencies": { "axios": "^0.27.2", "dotenv": "^16.4.5" } }, "sha512-PvkAGTuwtKXczJeoiLu2XQ4SzJh0m7Yr3ONJuvdjEAw95LwtfGxZ3Ip/w21kR94R4O260omLGlTcQvPf2ECnLg=="], + "caseless": ["caseless@0.12.0", "", {}, "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="], + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], "chai": ["chai@5.2.0", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw=="], @@ -2952,7 +2994,7 @@ "connect-history-api-fallback": ["connect-history-api-fallback@2.0.0", "", {}, "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA=="], - "consola": ["consola@3.4.0", "", {}, "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA=="], + "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], "console-control-strings": ["console-control-strings@1.1.0", "", {}, "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="], @@ -3296,7 +3338,7 @@ "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], - "electron-to-chromium": ["electron-to-chromium@1.5.119", "", {}, "sha512-Ku4NMzUjz3e3Vweh7PhApPrZSS4fyiCIbcIrG9eKrriYVLmbMepETR/v6SU7xPm98QTqMSYiCwfO89QNjXLkbQ=="], + "electron-to-chromium": ["electron-to-chromium@1.5.120", "", {}, "sha512-oTUp3gfX1gZI+xfD2djr2rzQdHCwHzPQrrK0CD7WpTdF0nPdQ/INcRVjWgLdCT4a9W3jFObR9DAfsuyFQnI8CQ=="], "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], @@ -3324,7 +3366,7 @@ "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - "env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="], + "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], "env-var": ["env-var@7.5.0", "", {}, "sha512-mKZOzLRN0ETzau2W2QXefbFjo5EF4yWq28OyKb9ICdeNhHJlOE/pHHnz4hdYJ9cNZXcJHo5xN4OT4pzuSHSNvA=="], @@ -3516,12 +3558,16 @@ "faye-websocket": ["faye-websocket@0.11.4", "", { "dependencies": { "websocket-driver": ">=0.5.1" } }, "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g=="], + "fbjs": ["fbjs@0.8.18", "", { "dependencies": { "core-js": "^1.0.0", "isomorphic-fetch": "^2.1.1", "loose-envify": "^1.0.0", "object-assign": "^4.1.0", "promise": "^7.1.1", "setimmediate": "^1.0.5", "ua-parser-js": "^0.7.30" } }, "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA=="], + "fclone": ["fclone@1.0.11", "", {}, "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw=="], "fdir": ["fdir@6.4.3", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw=="], "feed": ["feed@4.2.2", "", { "dependencies": { "xml-js": "^1.6.11" } }, "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ=="], + "ffmpeg-static": ["ffmpeg-static@5.2.0", "", { "dependencies": { "@derhuerst/http-basic": "^8.2.0", "env-paths": "^2.2.0", "https-proxy-agent": "^5.0.0", "progress": "^2.0.3" } }, "sha512-WrM7kLW+do9HLr+H6tk7LzQ7kPqbAgLjdzNE32+u3Ff11gXt9Kkkd2nusGFrlWMIe+XaA97t+I8JS7sZIrvRgA=="], + "figures": ["figures@3.2.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg=="], "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], @@ -3794,6 +3840,8 @@ "http-reasons": ["http-reasons@0.1.0", "", {}, "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ=="], + "http-response-object": ["http-response-object@3.0.2", "", { "dependencies": { "@types/node": "^10.0.3" } }, "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA=="], + "http2-client": ["http2-client@1.3.5", "", {}, "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA=="], "http2-wrapper": ["http2-wrapper@2.2.1", "", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" } }, "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ=="], @@ -3824,7 +3872,9 @@ "immer": ["immer@9.0.21", "", {}, "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA=="], - "immutable": ["immutable@5.0.3", "", {}, "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw=="], + "immutable": ["immutable@3.8.2", "", {}, "sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg=="], + + "immutablediff": ["immutablediff@0.4.4", "", { "dependencies": { "immutable": "^3.2.1" } }, "sha512-02YdiDFc8TdLrgsrCSazoA96zwL2Mt55NWFXZGgToKivQ9LaqTVoX0lQf8cw/lnckI3JhwFoDlyO1RqxQLxInw=="], "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], @@ -3984,6 +4034,8 @@ "isobject": ["isobject@3.0.1", "", {}, "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="], + "isomorphic-fetch": ["isomorphic-fetch@2.2.1", "", { "dependencies": { "node-fetch": "^1.0.1", "whatwg-fetch": ">=0.10.0" } }, "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA=="], + "isomorphic-ws": ["isomorphic-ws@4.0.1", "", { "peerDependencies": { "ws": "*" } }, "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w=="], "isows": ["isows@1.0.6", "", { "peerDependencies": { "ws": "*" } }, "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw=="], @@ -4152,6 +4204,8 @@ "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], + "lodash.mapvalues": ["lodash.mapvalues@4.6.0", "", {}, "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ=="], + "lodash.memoize": ["lodash.memoize@4.1.2", "", {}, "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="], "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], @@ -4162,6 +4216,8 @@ "lodash.uniq": ["lodash.uniq@4.5.0", "", {}, "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ=="], + "lodash.wrap": ["lodash.wrap@4.1.1", "", {}, "sha512-zOvgaTFh+7jBC80FKyoOwMyi8VF3LWAWuakrSXFVTIZAmrJEAYiu7lqwJYDhwh6l5wXuF5aGlzTBymvD+1q6LA=="], + "log-symbols": ["log-symbols@7.0.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-zrc91EDk2M+2AXo/9BTvK91pqb7qrPg2nX/Hy+u8a5qQlbaOflCKO+6SqgZ+M+xUFxGdKTgwnGiL96b1W3ikRA=="], "log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="], @@ -4428,7 +4484,7 @@ "nan": ["nan@2.22.2", "", {}, "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ=="], - "nanoid": ["nanoid@3.3.10", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg=="], + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="], @@ -4472,6 +4528,8 @@ "node-machine-id": ["node-machine-id@1.1.12", "", {}, "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ=="], + "node-opus": ["node-opus@0.3.3", "", { "dependencies": { "bindings": "~1.2.1", "commander": "^2.9.0", "nan": "^2.14.0" }, "optionalDependencies": { "ogg-packet": "^1.0.0" }, "os": [ "!aix", "!sunos", "!openbsd", ], "cpu": [ "arm", "x64", "ia32", "arm64", ] }, "sha512-ZQniA8iJ6y/qOTmW6eyzM9m8odt4CIGV0NM9/U03/pYLhGyxy18QXO25WfrWd8XsUYx57tnxll2xxj54CN08uQ=="], + "node-readfiles": ["node-readfiles@0.2.0", "", { "dependencies": { "es6-promise": "^3.2.1" } }, "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA=="], "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], @@ -4554,6 +4612,8 @@ "octokit": ["octokit@4.1.2", "", { "dependencies": { "@octokit/app": "^15.1.4", "@octokit/core": "^6.1.4", "@octokit/oauth-app": "^7.1.6", "@octokit/plugin-paginate-graphql": "^5.2.4", "@octokit/plugin-paginate-rest": "^11.4.2", "@octokit/plugin-rest-endpoint-methods": "^13.3.1", "@octokit/plugin-retry": "^7.1.4", "@octokit/plugin-throttling": "^9.4.0", "@octokit/request-error": "^6.1.7", "@octokit/types": "^13.7.0" } }, "sha512-0kcTxJOK3yQrJsRb8wKa28hlTze4QOz4sLuUnfXXnhboDhFKgv8LxS86tFwbsafDW9JZ08ByuVAE8kQbYJIZkA=="], + "ogg-packet": ["ogg-packet@1.0.1", "", { "dependencies": { "ref-struct": "*" } }, "sha512-dW1ok3BMnMikyXGDIgVEckWnlViW8JLWQV4qj9aN/rNRVqHlDYSlcIEtSIMH7tpuUOiIxAhY3+OxNdIOm6s17A=="], + "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="], "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], @@ -4574,7 +4634,7 @@ "open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="], - "openai": ["openai@4.87.3", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" }, "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-d2D54fzMuBYTxMW8wcNmhT1rYKcTfMJ8t+4KjH2KtvYenygITiGBgHoIrzHwnDQWW+C5oCA+ikIR2jgPCFqcKQ=="], + "openai": ["openai@4.88.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" }, "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-Ll2ZJCdX/56WcCF/wLtAFou+zWRyLeneoXy+qya5T5/wm5LkIr6heJfSn53c5ujXWPB+24cgumiOetbFqcppFA=="], "openapi-to-postmanv2": ["openapi-to-postmanv2@4.25.0", "", { "dependencies": { "ajv": "8.11.0", "ajv-draft-04": "1.0.0", "ajv-formats": "2.1.1", "async": "3.2.4", "commander": "2.20.3", "graphlib": "2.1.8", "js-yaml": "4.1.0", "json-pointer": "0.6.2", "json-schema-merge-allof": "0.8.1", "lodash": "4.17.21", "neotraverse": "0.6.15", "oas-resolver-browser": "2.5.6", "object-hash": "3.0.0", "path-browserify": "1.0.1", "postman-collection": "^4.4.0", "swagger2openapi": "7.0.8", "yaml": "1.10.2" }, "bin": { "openapi2postmanv2": "bin/openapi2postmanv2.js" } }, "sha512-sIymbkQby0gzxt2Yez8YKB6hoISEel05XwGwNrAhr6+vxJWXNxkmssQc/8UEtVkuJ9ZfUXLkip9PYACIpfPDWg=="], @@ -4584,6 +4644,8 @@ "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + "opusscript": ["opusscript@0.1.1", "", {}, "sha512-mL0fZZOUnXdZ78woRXp18lApwpp0lF5tozJOD1Wut0dgrA9WuQTgSels/CSmFleaAZrJi/nci5KOVtbuxeWoQA=="], + "ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="], "os-tmpdir": ["os-tmpdir@1.0.2", "", {}, "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="], @@ -4638,6 +4700,8 @@ "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + "parse-cache-control": ["parse-cache-control@1.0.1", "", {}, "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg=="], + "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], @@ -4692,7 +4756,7 @@ "pdfjs-dist": ["pdfjs-dist@4.7.76", "", { "optionalDependencies": { "canvas": "^2.11.2", "path2d": "^0.2.1" } }, "sha512-8y6wUgC/Em35IumlGjaJOCm3wV4aY/6sqnIT3fVW/67mXsOZ9HWBn8GDKmJUK0GSzpbmX3gQqwfoFayp78Mtqw=="], - "pg": ["pg@8.14.0", "", { "dependencies": { "pg-connection-string": "^2.7.0", "pg-pool": "^3.8.0", "pg-protocol": "^1.8.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, "optionalDependencies": { "pg-cloudflare": "^1.1.1" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-nXbVpyoaXVmdqlKEzToFf37qzyeeh7mbiXsnoWvstSqohj88yaa/I/Rq/HEVn2QPSZEuLIJa/jSpRDyzjEx4FQ=="], + "pg": ["pg@8.14.1", "", { "dependencies": { "pg-connection-string": "^2.7.0", "pg-pool": "^3.8.0", "pg-protocol": "^1.8.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, "optionalDependencies": { "pg-cloudflare": "^1.1.1" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-0TdbqfjwIun9Fm/r89oB7RFQ0bLgduAhiIqIXOsyKoiC/L54DbuAAzIEN/9Op0f1Po9X7iCPXGoa/Ah+2aI8Xw=="], "pg-cloudflare": ["pg-cloudflare@1.1.1", "", {}, "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q=="], @@ -4946,6 +5010,8 @@ "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="], + "promise": ["promise@7.3.1", "", { "dependencies": { "asap": "~2.0.3" } }, "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="], + "promise-inflight": ["promise-inflight@1.0.1", "", {}, "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g=="], "promise-retry": ["promise-retry@2.0.1", "", { "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g=="], @@ -4956,7 +5022,7 @@ "promzard": ["promzard@1.0.2", "", { "dependencies": { "read": "^3.0.1" } }, "sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ=="], - "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + "prop-types": ["prop-types@15.5.10", "", { "dependencies": { "fbjs": "^0.8.9", "loose-envify": "^1.3.1" } }, "sha512-vCFzoUFaZkVNeFkhK1KbSq4cn97GDrpfBt9K2qLkGnPAEFhEv3M61Lk5t+B7c0QfMLWo0fPkowk/4SuXerh26Q=="], "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], @@ -4988,7 +5054,7 @@ "qs": ["qs@6.13.0", "", { "dependencies": { "side-channel": "^1.0.6" } }, "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg=="], - "quansync": ["quansync@0.2.8", "", {}, "sha512-4+saucphJMazjt7iOM27mbFCk+D9dd/zmgMDCzRZ8MEoBfYp7lAvoN38et/phRQF6wOPMy/OROBGgoWeSKyluA=="], + "quansync": ["quansync@0.2.10", "", {}, "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A=="], "querystringify": ["querystringify@2.2.0", "", {}, "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="], @@ -5052,11 +5118,13 @@ "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], - "react-router": ["react-router@7.3.0", "", { "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0", "turbo-stream": "2.4.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-466f2W7HIWaNXTKM5nHTqNxLrHTyXybm7R0eBlVSt0k/u55tTCDO194OIx/NrYD4TS5SXKTNekXfT37kMKUjgw=="], + "react-resizable-panels": ["react-resizable-panels@2.1.7", "", { "peerDependencies": { "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-JtT6gI+nURzhMYQYsx8DKkx6bSoOGFp7A3CwMrOb8y5jFHFyqwo9m68UhmXRw57fRVJksFn1TSlm3ywEQ9vMgA=="], + + "react-router": ["react-router@7.4.0", "", { "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0", "turbo-stream": "2.4.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-Y2g5ObjkvX3VFeVt+0CIPuYd9PpgqCslG7ASSIdN73LwA1nNWzcMLaoMRJfP3prZFI92svxFwbn7XkLJ+UPQ6A=="], "react-router-config": ["react-router-config@5.1.1", "", { "dependencies": { "@babel/runtime": "^7.1.2" }, "peerDependencies": { "react": ">=15", "react-router": ">=5" } }, "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg=="], - "react-router-dom": ["react-router-dom@7.3.0", "", { "dependencies": { "react-router": "7.3.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-z7Q5FTiHGgQfEurX/FBinkOXhWREJIAB2RiU24lvcBa82PxUpwqvs/PAXb9lJyPjTs2jrl6UkLvCZVGJPeNuuQ=="], + "react-router-dom": ["react-router-dom@7.4.0", "", { "dependencies": { "react-router": "7.4.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-VlksBPf3n2bijPvnA7nkTsXxMAKOj+bWp4R9c3i+bnwlSOFAGOkJkKhzy/OsRkWaBMICqcAl1JDzh9ZSOze9CA=="], "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], @@ -5108,6 +5176,10 @@ "redux-thunk": ["redux-thunk@2.4.2", "", { "peerDependencies": { "redux": "^4" } }, "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q=="], + "ref": ["ref@1.3.5", "", { "dependencies": { "bindings": "1", "debug": "2", "nan": "2" } }, "sha512-2cBCniTtxcGUjDpvFfVpw323a83/0RLSGJJY5l5lcomZWhYpU2cuLdsvYqMixvsdLJ9+sTdzEkju8J8ZHDM2nA=="], + + "ref-struct": ["ref-struct@1.1.0", "", { "dependencies": { "debug": "2", "ref": "1" } }, "sha512-h2OSdAUycdqiwFBp2wB3XEFheWA/U+n/JYnhEi3584JqnCCDXIA3qDIhHH3klIHMNZwrJW+VagpxPGeSf6777Q=="], + "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], "reftools": ["reftools@1.1.9", "", {}, "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w=="], @@ -5206,7 +5278,7 @@ "rpc-websockets": ["rpc-websockets@9.1.1", "", { "dependencies": { "@swc/helpers": "^0.5.11", "@types/uuid": "^8.3.4", "@types/ws": "^8.2.2", "buffer": "^6.0.3", "eventemitter3": "^5.0.1", "uuid": "^8.3.2", "ws": "^8.5.0" }, "optionalDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" } }, "sha512-1IXGM/TfPT6nfYMIXkJdzn+L4JEsmb0FL1O2OBjaH03V3yuUDdKFulGLMFG6ErV+8pZ5HVC0limve01RyO+saA=="], - "rspack-resolver": ["rspack-resolver@1.1.2", "", { "optionalDependencies": { "@unrs/rspack-resolver-binding-darwin-arm64": "1.1.2", "@unrs/rspack-resolver-binding-darwin-x64": "1.1.2", "@unrs/rspack-resolver-binding-freebsd-x64": "1.1.2", "@unrs/rspack-resolver-binding-linux-arm-gnueabihf": "1.1.2", "@unrs/rspack-resolver-binding-linux-arm64-gnu": "1.1.2", "@unrs/rspack-resolver-binding-linux-arm64-musl": "1.1.2", "@unrs/rspack-resolver-binding-linux-x64-gnu": "1.1.2", "@unrs/rspack-resolver-binding-linux-x64-musl": "1.1.2", "@unrs/rspack-resolver-binding-wasm32-wasi": "1.1.2", "@unrs/rspack-resolver-binding-win32-arm64-msvc": "1.1.2", "@unrs/rspack-resolver-binding-win32-x64-msvc": "1.1.2" } }, "sha512-eHhz+9JWHFdbl/CVVqEP6kviLFZqw1s0MWxLdsGMtUKUspSO3SERptPohmrUIC9jT1bGV9Bd3+r8AmWbdfNAzQ=="], + "rspack-resolver": ["rspack-resolver@1.2.2", "", { "optionalDependencies": { "@unrs/rspack-resolver-binding-darwin-arm64": "1.2.2", "@unrs/rspack-resolver-binding-darwin-x64": "1.2.2", "@unrs/rspack-resolver-binding-freebsd-x64": "1.2.2", "@unrs/rspack-resolver-binding-linux-arm-gnueabihf": "1.2.2", "@unrs/rspack-resolver-binding-linux-arm64-gnu": "1.2.2", "@unrs/rspack-resolver-binding-linux-arm64-musl": "1.2.2", "@unrs/rspack-resolver-binding-linux-x64-gnu": "1.2.2", "@unrs/rspack-resolver-binding-linux-x64-musl": "1.2.2", "@unrs/rspack-resolver-binding-wasm32-wasi": "1.2.2", "@unrs/rspack-resolver-binding-win32-arm64-msvc": "1.2.2", "@unrs/rspack-resolver-binding-win32-x64-msvc": "1.2.2" } }, "sha512-Fwc19jMBA3g+fxDJH2B4WxwZjE0VaaOL7OX/A4Wn5Zv7bOD/vyPZhzXfaO73Xc2GAlfi96g5fGUa378WbIGfFw=="], "rtlcss": ["rtlcss@4.3.0", "", { "dependencies": { "escalade": "^3.1.1", "picocolors": "^1.0.0", "postcss": "^8.4.21", "strip-json-comments": "^3.1.1" }, "bin": { "rtlcss": "bin/rtlcss.js" } }, "sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig=="], @@ -5238,7 +5310,7 @@ "sandwich-stream": ["sandwich-stream@2.0.2", "", {}, "sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ=="], - "sass": ["sass@1.85.1", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag=="], + "sass": ["sass@1.86.0", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-zV8vGUld/+mP4KbMLJMX7TyGCuUp7hnkOScgCMsWuHtns8CWBoz+vmEhoGMXsaJrbUP8gj+F1dLvVe79sK8UdA=="], "sass-loader": ["sass-loader@16.0.5", "", { "dependencies": { "neo-async": "^2.6.2" }, "peerDependencies": { "@rspack/core": "0.x || 1.x", "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "sass": "^1.3.0", "sass-embedded": "*", "webpack": "^5.0.0" }, "optionalPeers": ["@rspack/core", "node-sass", "sass", "sass-embedded", "webpack"] }, "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw=="], @@ -5286,6 +5358,8 @@ "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="], + "setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="], + "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], "shallow-clone": ["shallow-clone@3.0.1", "", { "dependencies": { "kind-of": "^6.0.2" } }, "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA=="], @@ -5554,6 +5628,8 @@ "thunky": ["thunky@1.1.0", "", {}, "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="], + "tide": ["tide@2.3.0", "", { "dependencies": { "immutable": "^3.8.1", "immutablediff": "^0.4.4", "lodash.mapvalues": "^4.6.0", "lodash.wrap": "^4.1.1", "prop-types": "~15.5.8", "shallowequal": "^1.0.1" }, "peerDependencies": { "react": "^0.14.3 || ^15.0" } }, "sha512-7kbwVx7Tb7N/MtBAl2RW1s7hME/MW7FM8FjL8QrVLxwX/luNhB+VxkGRwVXURnWVSjw7HPhZvvhJ5JKYvnOAug=="], + "time-span": ["time-span@5.1.0", "", { "dependencies": { "convert-hrtime": "^5.0.0" } }, "sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA=="], "timers-ext": ["timers-ext@0.1.8", "", { "dependencies": { "es5-ext": "^0.10.64", "next-tick": "^1.1.0" } }, "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww=="], @@ -5678,7 +5754,9 @@ "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], - "typescript-eslint": ["typescript-eslint@8.26.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.26.1", "@typescript-eslint/parser": "8.26.1", "@typescript-eslint/utils": "8.26.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-t/oIs9mYyrwZGRpDv3g+3K6nZ5uhKEMt2oNmAPwaY4/ye0+EH4nXIPYNtkYFS6QHm+1DFg34DbglYBz5P9Xysg=="], + "typescript-eslint": ["typescript-eslint@8.27.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.27.0", "@typescript-eslint/parser": "8.27.0", "@typescript-eslint/utils": "8.27.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-ZZ/8+Y0rRUMuW1gJaPtLWe4ryHbsPLzzibk5Sq+IFa2aOH1Vo0gPr1fbA6pOnzBke7zC2Da4w8AyCgxKXo3lqA=="], + + "ua-parser-js": ["ua-parser-js@0.7.40", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ=="], "uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="], @@ -5732,7 +5810,7 @@ "unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="], - "universal-github-app-jwt": ["universal-github-app-jwt@2.2.0", "", {}, "sha512-G5o6f95b5BggDGuUfKDApKaCgNYy2x7OdHY0zSMF081O0EJobw+1130VONhrA7ezGSV2FNOGyM+KQpQZAr9bIQ=="], + "universal-github-app-jwt": ["universal-github-app-jwt@2.2.2", "", {}, "sha512-dcmbeSrOdTnsjGjUfAlqNDJrhxXizjAz94ija9Qw8YkZ1uu0d+GoZzyH+Jb9tIIqvGsadUfwg+22k5aDqqwzbw=="], "universal-user-agent": ["universal-user-agent@7.0.2", "", {}, "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q=="], @@ -5874,6 +5952,8 @@ "websocket-extensions": ["websocket-extensions@0.1.4", "", {}, "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="], + "whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="], + "whatwg-url": ["whatwg-url@7.1.0", "", { "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg=="], "which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="], @@ -5952,7 +6032,7 @@ "zwitch": ["zwitch@1.0.5", "", {}, "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw=="], - "@ai-sdk/react/@ai-sdk/ui-utils": ["@ai-sdk/ui-utils@1.1.19", "", { "dependencies": { "@ai-sdk/provider": "1.0.11", "@ai-sdk/provider-utils": "2.1.13", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.0.0" }, "optionalPeers": ["zod"] }, "sha512-rDHy2uxlPMt3jjS9L6mBrsfhEInZ5BVoWevmD13fsAt2s/XWy2OwwKmgmUQkdLlY4mn/eyeYAfDGK8+5CbOAgg=="], + "@ai-sdk/react/@ai-sdk/ui-utils": ["@ai-sdk/ui-utils@1.1.20", "", { "dependencies": { "@ai-sdk/provider": "1.0.12", "@ai-sdk/provider-utils": "2.1.14", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.0.0" }, "optionalPeers": ["zod"] }, "sha512-k+qQh1YA8/kH12d8KQFWjr0UxyS9nLibzbLr2OY6fzpfZg8xIAKlZeH952JIp2XwAp72tesgbsAmA15cDldtyw=="], "@ai-sdk/ui-utils/@ai-sdk/provider": ["@ai-sdk/provider@1.0.7", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-q1PJEZ0qD9rVR+8JFEd01/QM++csMT5UVwYXSN2u54BrVw/D8TZLTeg2FEfKK00DgAx0UtWd8XOhhwITP9BT5g=="], @@ -5962,6 +6042,8 @@ "@anthropic-ai/sdk/formdata-node": ["formdata-node@4.4.1", "", { "dependencies": { "node-domexception": "1.0.0", "web-streams-polyfill": "4.0.0-beta.3" } }, "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ=="], + "@anthropic-ai/sdk/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + "@aws-crypto/sha1-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], "@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], @@ -6000,6 +6082,8 @@ "@csstools/selector-specificity/postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="], + "@derhuerst/http-basic/concat-stream": ["concat-stream@2.0.0", "", { "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.0.2", "typedarray": "^0.0.6" } }, "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A=="], + "@discordjs/builders/@discordjs/formatters": ["@discordjs/formatters@0.6.0", "", { "dependencies": { "discord-api-types": "^0.37.114" } }, "sha512-YIruKw4UILt/ivO4uISmrGq2GdMY6EkoTtD0oS0GvkJFRZbTSdPhzYiUILbJ/QslsvC9H9nTgGgnarnIl4jMfw=="], "@discordjs/builders/discord-api-types": ["discord-api-types@0.37.119", "", {}, "sha512-WasbGFXEB+VQWXlo6IpW3oUv73Yuau1Ig4AZF/m13tXcTKnMpc/mHjpztIlz4+BM9FG9BHQkEXiPto3bKduQUg=="], @@ -6078,6 +6162,8 @@ "@elizaos/plugin-storage-s3/@types/uuid": ["@types/uuid@10.0.0", "", {}, "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ=="], + "@elizaos/plugin-storage-s3/@vitest/coverage-v8": ["@vitest/coverage-v8@1.1.3", "", { "dependencies": { "@ampproject/remapping": "^2.2.1", "@bcoe/v8-coverage": "^0.2.3", "debug": "^4.3.4", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^4.0.1", "istanbul-reports": "^3.1.6", "magic-string": "^0.30.5", "magicast": "^0.3.2", "picocolors": "^1.0.0", "std-env": "^3.5.0", "test-exclude": "^6.0.0", "v8-to-istanbul": "^9.2.0" }, "peerDependencies": { "vitest": "^1.0.0" } }, "sha512-Uput7t3eIcbSTOTQBzGtS+0kah96bX+szW9qQrLeGe3UmgL2Akn8POnyC2lH7XsnREZOds9aCUTxgXf+4HX5RA=="], + "@elizaos/plugin-storage-s3/glob": ["glob@11.0.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^4.0.1", "minimatch": "^10.0.0", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g=="], "@elizaos/plugin-tee/@types/node": ["@types/node@20.17.24", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-d7fGCyB96w9BnWQrOsJtpyiSaBcAYYr75bnK6ZRjDbql2cGLj/3GsL5OYmLPNq76l7Gf2q4Rv9J2o6h5CrD9sA=="], @@ -6092,7 +6178,7 @@ "@elizaos/plugin-video-understanding/glob": ["glob@11.0.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^4.0.1", "minimatch": "^10.0.0", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g=="], - "@elizaos/the-org/@types/react": ["@types/react@18.3.18", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" } }, "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ=="], + "@elizaos/the-org/@types/react": ["@types/react@18.3.19", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" } }, "sha512-fcdJqaHOMDbiAwJnXv6XCzX0jDW77yI3tJqYh1Byn8EL5/S628WRx9b/y3DnNe55zTukUQKrfYxiZls2dHcUMw=="], "@elizaos/the-org/@types/react-dom": ["@types/react-dom@18.3.5", "", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q=="], @@ -6266,9 +6352,7 @@ "@yarnpkg/parsers/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], - "ai/@ai-sdk/ui-utils": ["@ai-sdk/ui-utils@1.1.19", "", { "dependencies": { "@ai-sdk/provider": "1.0.11", "@ai-sdk/provider-utils": "2.1.13", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.0.0" }, "optionalPeers": ["zod"] }, "sha512-rDHy2uxlPMt3jjS9L6mBrsfhEInZ5BVoWevmD13fsAt2s/XWy2OwwKmgmUQkdLlY4mn/eyeYAfDGK8+5CbOAgg=="], - - "ajv-formats/ajv": ["ajv@8.11.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg=="], + "ai/@ai-sdk/ui-utils": ["@ai-sdk/ui-utils@1.1.20", "", { "dependencies": { "@ai-sdk/provider": "1.0.12", "@ai-sdk/provider-utils": "2.1.14", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.0.0" }, "optionalPeers": ["zod"] }, "sha512-k+qQh1YA8/kH12d8KQFWjr0UxyS9nLibzbLr2OY6fzpfZg8xIAKlZeH952JIp2XwAp72tesgbsAmA15cDldtyw=="], "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], @@ -6276,6 +6360,8 @@ "babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "bigint-buffer/bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="], + "binary-version/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="], "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -6448,6 +6534,8 @@ "eslint-plugin-react/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "eslint-plugin-react/prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "estree-util-build-jsx/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], @@ -6466,6 +6554,10 @@ "fastembed/onnxruntime-node": ["onnxruntime-node@1.15.1", "", { "dependencies": { "onnxruntime-common": "~1.15.1" }, "os": [ "linux", "win32", "darwin", ] }, "sha512-wzhVELulmrvNoMZw0/HfV+9iwgHX+kPS82nxodZ37WCXmbeo1jp3thamTsNg8MGhxvv4GmEzRum5mo40oqIsqw=="], + "fbjs/core-js": ["core-js@1.2.7", "", {}, "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA=="], + + "ffmpeg-static/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + "figures/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], "file-loader/loader-utils": ["loader-utils@2.0.4", "", { "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", "json5": "^2.1.2" } }, "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw=="], @@ -6500,6 +6592,8 @@ "gauge/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "gel/env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="], + "gel/which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="], "get-pkg-repo/hosted-git-info": ["hosted-git-info@4.1.0", "", { "dependencies": { "lru-cache": "^6.0.0" } }, "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA=="], @@ -6592,6 +6686,8 @@ "http-proxy-middleware/is-plain-obj": ["is-plain-obj@3.0.0", "", {}, "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA=="], + "http-response-object/@types/node": ["@types/node@10.17.60", "", {}, "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw=="], + "http2-wrapper/quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="], "ignore-walk/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], @@ -6616,6 +6712,8 @@ "ipull/pretty-ms": ["pretty-ms@8.0.0", "", { "dependencies": { "parse-ms": "^3.0.0" } }, "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q=="], + "isomorphic-fetch/node-fetch": ["node-fetch@1.7.3", "", { "dependencies": { "encoding": "^0.1.11", "is-stream": "^1.0.1" } }, "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ=="], + "istanbul-lib-report/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "jake/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], @@ -6910,8 +7008,6 @@ "node-fetch/whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], - "node-gyp/env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], - "node-gyp/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], "node-gyp/make-fetch-happen": ["make-fetch-happen@13.0.1", "", { "dependencies": { "@npmcli/agent": "^2.0.0", "cacache": "^18.0.0", "http-cache-semantics": "^4.1.1", "is-lambda": "^1.0.1", "minipass": "^7.0.2", "minipass-fetch": "^3.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "proc-log": "^4.2.0", "promise-retry": "^2.0.1", "ssri": "^10.0.0" } }, "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA=="], @@ -6926,12 +7022,14 @@ "node-llama-cpp/ignore": ["ignore@7.0.3", "", {}, "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA=="], - "node-llama-cpp/nanoid": ["nanoid@5.1.4", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-GTFcMIDgR7tqji/LpSY8rtg464VnJl/j6ypoehYnuGb+Y8qZUdtKB8WVCXon0UEZgFDbuUxpIl//6FHLHgXSNA=="], + "node-llama-cpp/nanoid": ["nanoid@5.1.5", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw=="], "node-llama-cpp/validate-npm-package-name": ["validate-npm-package-name@6.0.0", "", {}, "sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg=="], "node-llama-cpp/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], + "node-opus/commander": ["commander@2.15.1", "", {}, "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag=="], + "nodemon/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], "nodemon/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], @@ -7110,6 +7208,8 @@ "react-dev-utils/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "react-helmet-async/prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + "react-live/prism-react-renderer": ["prism-react-renderer@2.4.1", "", { "dependencies": { "@types/prismjs": "^1.26.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": ">=16.0.0" } }, "sha512-ey8Ls/+Di31eqzUxC46h8MksNuGx/n0AAC8uKpwFau4RPDYLuE3EXTp8N8G2vX2N7UC/+IXeNUnlWBGGcAG+Ig=="], "react-markdown/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="], @@ -7120,6 +7220,8 @@ "react-markdown/hast-util-whitespace": ["hast-util-whitespace@2.0.1", "", {}, "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng=="], + "react-markdown/prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + "react-markdown/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="], "react-markdown/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], @@ -7136,8 +7238,14 @@ "react-markdown/vfile": ["vfile@5.3.7", "", { "dependencies": { "@types/unist": "^2.0.0", "is-buffer": "^2.0.0", "unist-util-stringify-position": "^3.0.0", "vfile-message": "^3.0.0" } }, "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g=="], + "react-modal/prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + + "react-redux/prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + "react-redux/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="], + "react-waypoint/prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + "react-waypoint/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], "read/mute-stream": ["mute-stream@1.0.0", "", {}, "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA=="], @@ -7172,6 +7280,12 @@ "recursive-readdir/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "ref/bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="], + + "ref/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "ref-struct/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + "regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], "rehype-parse/parse5": ["parse5@6.0.1", "", {}, "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="], @@ -7222,7 +7336,7 @@ "rpc-websockets/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], - "schema-utils/ajv": ["ajv@8.11.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg=="], + "sass/immutable": ["immutable@5.0.3", "", {}, "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw=="], "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -7342,15 +7456,15 @@ "ts-node/diff": ["diff@4.0.2", "", {}, "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="], - "tsup/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="], + "tsup/rollup": ["rollup@4.36.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.36.0", "@rollup/rollup-android-arm64": "4.36.0", "@rollup/rollup-darwin-arm64": "4.36.0", "@rollup/rollup-darwin-x64": "4.36.0", "@rollup/rollup-freebsd-arm64": "4.36.0", "@rollup/rollup-freebsd-x64": "4.36.0", "@rollup/rollup-linux-arm-gnueabihf": "4.36.0", "@rollup/rollup-linux-arm-musleabihf": "4.36.0", "@rollup/rollup-linux-arm64-gnu": "4.36.0", "@rollup/rollup-linux-arm64-musl": "4.36.0", "@rollup/rollup-linux-loongarch64-gnu": "4.36.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.36.0", "@rollup/rollup-linux-riscv64-gnu": "4.36.0", "@rollup/rollup-linux-s390x-gnu": "4.36.0", "@rollup/rollup-linux-x64-gnu": "4.36.0", "@rollup/rollup-linux-x64-musl": "4.36.0", "@rollup/rollup-win32-arm64-msvc": "4.36.0", "@rollup/rollup-win32-ia32-msvc": "4.36.0", "@rollup/rollup-win32-x64-msvc": "4.36.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q=="], "typedoc/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "typescript-eslint/@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.26.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/type-utils": "8.26.1", "@typescript-eslint/utils": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA=="], + "typescript-eslint/@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.27.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.27.0", "@typescript-eslint/type-utils": "8.27.0", "@typescript-eslint/utils": "8.27.0", "@typescript-eslint/visitor-keys": "8.27.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA=="], - "typescript-eslint/@typescript-eslint/parser": ["@typescript-eslint/parser@8.26.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/types": "8.26.1", "@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ=="], + "typescript-eslint/@typescript-eslint/parser": ["@typescript-eslint/parser@8.27.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.27.0", "@typescript-eslint/types": "8.27.0", "@typescript-eslint/typescript-estree": "8.27.0", "@typescript-eslint/visitor-keys": "8.27.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA=="], - "typescript-eslint/@typescript-eslint/utils": ["@typescript-eslint/utils@8.26.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.26.1", "@typescript-eslint/types": "8.26.1", "@typescript-eslint/typescript-estree": "8.26.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg=="], + "typescript-eslint/@typescript-eslint/utils": ["@typescript-eslint/utils@8.27.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.27.0", "@typescript-eslint/types": "8.27.0", "@typescript-eslint/typescript-estree": "8.27.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q=="], "unified/vfile": ["vfile@4.2.1", "", { "dependencies": { "@types/unist": "^2.0.0", "is-buffer": "^2.0.0", "unist-util-stringify-position": "^2.0.0", "vfile-message": "^2.0.0" } }, "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA=="], @@ -7376,7 +7490,7 @@ "vite/esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], - "vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="], + "vite/rollup": ["rollup@4.36.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.36.0", "@rollup/rollup-android-arm64": "4.36.0", "@rollup/rollup-darwin-arm64": "4.36.0", "@rollup/rollup-darwin-x64": "4.36.0", "@rollup/rollup-freebsd-arm64": "4.36.0", "@rollup/rollup-freebsd-x64": "4.36.0", "@rollup/rollup-linux-arm-gnueabihf": "4.36.0", "@rollup/rollup-linux-arm-musleabihf": "4.36.0", "@rollup/rollup-linux-arm64-gnu": "4.36.0", "@rollup/rollup-linux-arm64-musl": "4.36.0", "@rollup/rollup-linux-loongarch64-gnu": "4.36.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.36.0", "@rollup/rollup-linux-riscv64-gnu": "4.36.0", "@rollup/rollup-linux-s390x-gnu": "4.36.0", "@rollup/rollup-linux-x64-gnu": "4.36.0", "@rollup/rollup-linux-x64-musl": "4.36.0", "@rollup/rollup-win32-arm64-msvc": "4.36.0", "@rollup/rollup-win32-ia32-msvc": "4.36.0", "@rollup/rollup-win32-x64-msvc": "4.36.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q=="], "vite-node/vite": ["vite@6.2.2", "", { "dependencies": { "esbuild": "^0.25.0", "postcss": "^8.5.3", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ=="], @@ -7420,6 +7534,8 @@ "@anthropic-ai/sdk/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], + "@anthropic-ai/sdk/node-fetch/whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + "@aws-crypto/sha1-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], @@ -7430,6 +7546,10 @@ "@docusaurus/core/react-router/path-to-regexp": ["path-to-regexp@1.9.0", "", { "dependencies": { "isarray": "0.0.1" } }, "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g=="], + "@docusaurus/core/react-router/prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + + "@docusaurus/core/react-router-dom/prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + "@docusaurus/lqip-loader/sharp/node-addon-api": ["node-addon-api@6.1.0", "", {}, "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="], "@docusaurus/lqip-loader/sharp/tar-fs": ["tar-fs@3.0.8", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg=="], @@ -7452,15 +7572,17 @@ "@docusaurus/plugin-ideal-image/sharp/tar-fs": ["tar-fs@3.0.8", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg=="], + "@docusaurus/theme-classic/react-router-dom/prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + "@docusaurus/theme-classic/react-router-dom/react-router": ["react-router@5.3.4", "", { "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", "hoist-non-react-statics": "^3.1.0", "loose-envify": "^1.3.1", "path-to-regexp": "^1.7.0", "prop-types": "^15.6.2", "react-is": "^16.6.0", "tiny-invariant": "^1.0.2", "tiny-warning": "^1.0.0" }, "peerDependencies": { "react": ">=15" } }, "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA=="], - "@elizaos/app/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="], + "@elizaos/app/vite/rollup": ["rollup@4.36.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.36.0", "@rollup/rollup-android-arm64": "4.36.0", "@rollup/rollup-darwin-arm64": "4.36.0", "@rollup/rollup-darwin-x64": "4.36.0", "@rollup/rollup-freebsd-arm64": "4.36.0", "@rollup/rollup-freebsd-x64": "4.36.0", "@rollup/rollup-linux-arm-gnueabihf": "4.36.0", "@rollup/rollup-linux-arm-musleabihf": "4.36.0", "@rollup/rollup-linux-arm64-gnu": "4.36.0", "@rollup/rollup-linux-arm64-musl": "4.36.0", "@rollup/rollup-linux-loongarch64-gnu": "4.36.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.36.0", "@rollup/rollup-linux-riscv64-gnu": "4.36.0", "@rollup/rollup-linux-s390x-gnu": "4.36.0", "@rollup/rollup-linux-x64-gnu": "4.36.0", "@rollup/rollup-linux-x64-musl": "4.36.0", "@rollup/rollup-win32-arm64-msvc": "4.36.0", "@rollup/rollup-win32-ia32-msvc": "4.36.0", "@rollup/rollup-win32-x64-msvc": "4.36.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q=="], "@elizaos/autodoc/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], "@elizaos/cli/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], - "@elizaos/client/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="], + "@elizaos/client/vite/rollup": ["rollup@4.36.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.36.0", "@rollup/rollup-android-arm64": "4.36.0", "@rollup/rollup-darwin-arm64": "4.36.0", "@rollup/rollup-darwin-x64": "4.36.0", "@rollup/rollup-freebsd-arm64": "4.36.0", "@rollup/rollup-freebsd-x64": "4.36.0", "@rollup/rollup-linux-arm-gnueabihf": "4.36.0", "@rollup/rollup-linux-arm-musleabihf": "4.36.0", "@rollup/rollup-linux-arm64-gnu": "4.36.0", "@rollup/rollup-linux-arm64-musl": "4.36.0", "@rollup/rollup-linux-loongarch64-gnu": "4.36.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.36.0", "@rollup/rollup-linux-riscv64-gnu": "4.36.0", "@rollup/rollup-linux-s390x-gnu": "4.36.0", "@rollup/rollup-linux-x64-gnu": "4.36.0", "@rollup/rollup-linux-x64-musl": "4.36.0", "@rollup/rollup-win32-arm64-msvc": "4.36.0", "@rollup/rollup-win32-ia32-msvc": "4.36.0", "@rollup/rollup-win32-x64-msvc": "4.36.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q=="], "@elizaos/core/glob/minimatch": ["minimatch@10.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="], @@ -7480,7 +7602,7 @@ "@elizaos/plugin-evm/tsup/esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], - "@elizaos/plugin-evm/tsup/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="], + "@elizaos/plugin-evm/tsup/rollup": ["rollup@4.36.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.36.0", "@rollup/rollup-android-arm64": "4.36.0", "@rollup/rollup-darwin-arm64": "4.36.0", "@rollup/rollup-darwin-x64": "4.36.0", "@rollup/rollup-freebsd-arm64": "4.36.0", "@rollup/rollup-freebsd-x64": "4.36.0", "@rollup/rollup-linux-arm-gnueabihf": "4.36.0", "@rollup/rollup-linux-arm-musleabihf": "4.36.0", "@rollup/rollup-linux-arm64-gnu": "4.36.0", "@rollup/rollup-linux-arm64-musl": "4.36.0", "@rollup/rollup-linux-loongarch64-gnu": "4.36.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.36.0", "@rollup/rollup-linux-riscv64-gnu": "4.36.0", "@rollup/rollup-linux-s390x-gnu": "4.36.0", "@rollup/rollup-linux-x64-gnu": "4.36.0", "@rollup/rollup-linux-x64-musl": "4.36.0", "@rollup/rollup-win32-arm64-msvc": "4.36.0", "@rollup/rollup-win32-ia32-msvc": "4.36.0", "@rollup/rollup-win32-x64-msvc": "4.36.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q=="], "@elizaos/plugin-local-ai/glob/minimatch": ["minimatch@10.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="], @@ -7490,6 +7612,10 @@ "@elizaos/plugin-storage-s3/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], + "@elizaos/plugin-storage-s3/@vitest/coverage-v8/istanbul-lib-source-maps": ["istanbul-lib-source-maps@4.0.1", "", { "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" } }, "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw=="], + + "@elizaos/plugin-storage-s3/@vitest/coverage-v8/test-exclude": ["test-exclude@6.0.0", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" } }, "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w=="], + "@elizaos/plugin-storage-s3/glob/minimatch": ["minimatch@10.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="], "@elizaos/plugin-tee/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], @@ -7504,7 +7630,7 @@ "@elizaos/plugin-video-understanding/glob/minimatch": ["minimatch@10.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="], - "@elizaos/the-org/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="], + "@elizaos/the-org/vite/rollup": ["rollup@4.36.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.36.0", "@rollup/rollup-android-arm64": "4.36.0", "@rollup/rollup-darwin-arm64": "4.36.0", "@rollup/rollup-darwin-x64": "4.36.0", "@rollup/rollup-freebsd-arm64": "4.36.0", "@rollup/rollup-freebsd-x64": "4.36.0", "@rollup/rollup-linux-arm-gnueabihf": "4.36.0", "@rollup/rollup-linux-arm-musleabihf": "4.36.0", "@rollup/rollup-linux-arm64-gnu": "4.36.0", "@rollup/rollup-linux-arm64-musl": "4.36.0", "@rollup/rollup-linux-loongarch64-gnu": "4.36.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.36.0", "@rollup/rollup-linux-riscv64-gnu": "4.36.0", "@rollup/rollup-linux-s390x-gnu": "4.36.0", "@rollup/rollup-linux-x64-gnu": "4.36.0", "@rollup/rollup-linux-x64-musl": "4.36.0", "@rollup/rollup-win32-arm64-msvc": "4.36.0", "@rollup/rollup-win32-ia32-msvc": "4.36.0", "@rollup/rollup-win32-x64-msvc": "4.36.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], @@ -7778,6 +7904,8 @@ "fastembed/onnxruntime-node/onnxruntime-common": ["onnxruntime-common@1.15.1", "", {}, "sha512-Y89eJ8QmaRsPZPWLaX7mfqhj63ny47rSkQe80hIo+lvBQdrdXYR9VO362xvZulk9DFkCnXmGidprvgJ07bKsIQ=="], + "ffmpeg-static/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + "file-loader/schema-utils/ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], "file-loader/schema-utils/ajv-keywords": ["ajv-keywords@3.5.2", "", { "peerDependencies": { "ajv": "^6.9.1" } }, "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="], @@ -7872,6 +8000,8 @@ "ipull/pretty-ms/parse-ms": ["parse-ms@3.0.0", "", {}, "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw=="], + "isomorphic-fetch/node-fetch/is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="], + "jayson/@types/ws/@types/node": ["@types/node@22.13.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw=="], "lerna/@octokit/rest/@octokit/core": ["@octokit/core@4.2.4", "", { "dependencies": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", "@octokit/request": "^6.0.0", "@octokit/request-error": "^3.0.0", "@octokit/types": "^9.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" } }, "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ=="], @@ -8176,6 +8306,8 @@ "react-dev-utils/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "react-markdown/prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], + "react-markdown/remark-parse/mdast-util-from-markdown": ["mdast-util-from-markdown@1.3.1", "", { "dependencies": { "@types/mdast": "^3.0.0", "@types/unist": "^2.0.0", "decode-named-character-reference": "^1.0.0", "mdast-util-to-string": "^3.1.0", "micromark": "^3.0.0", "micromark-util-decode-numeric-character-reference": "^1.0.0", "micromark-util-decode-string": "^1.0.0", "micromark-util-normalize-identifier": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0", "unist-util-stringify-position": "^3.0.0", "uvu": "^0.5.0" } }, "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww=="], "react-markdown/remark-rehype/mdast-util-to-hast": ["mdast-util-to-hast@12.3.0", "", { "dependencies": { "@types/hast": "^2.0.0", "@types/mdast": "^3.0.0", "mdast-util-definitions": "^5.0.0", "micromark-util-sanitize-uri": "^1.1.0", "trim-lines": "^3.0.0", "unist-util-generated": "^2.0.0", "unist-util-position": "^4.0.0", "unist-util-visit": "^4.0.0" } }, "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw=="], @@ -8194,6 +8326,10 @@ "react-markdown/vfile/vfile-message": ["vfile-message@3.1.4", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-stringify-position": "^3.0.0" } }, "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw=="], + "react-redux/prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], + + "react-waypoint/prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], + "read-package-json/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], "read-package-json/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], @@ -8234,6 +8370,10 @@ "recma-stringify/unified/trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], + "ref-struct/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "ref/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "rehype-raw/@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], "rehype-raw/unified/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], @@ -8364,25 +8504,25 @@ "typedoc/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1" } }, "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg=="], + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.27.0", "", { "dependencies": { "@typescript-eslint/types": "8.27.0", "@typescript-eslint/visitor-keys": "8.27.0" } }, "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw=="], - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.26.1", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.26.1", "@typescript-eslint/utils": "8.26.1", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg=="], + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.27.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.27.0", "@typescript-eslint/utils": "8.27.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA=="], - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "eslint-visitor-keys": "^4.2.0" } }, "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg=="], + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.27.0", "", { "dependencies": { "@typescript-eslint/types": "8.27.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ=="], - "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1" } }, "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg=="], + "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.27.0", "", { "dependencies": { "@typescript-eslint/types": "8.27.0", "@typescript-eslint/visitor-keys": "8.27.0" } }, "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw=="], - "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.26.1", "", {}, "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ=="], + "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.27.0", "", {}, "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A=="], - "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA=="], + "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.27.0", "", { "dependencies": { "@typescript-eslint/types": "8.27.0", "@typescript-eslint/visitor-keys": "8.27.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A=="], - "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "eslint-visitor-keys": "^4.2.0" } }, "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg=="], + "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.27.0", "", { "dependencies": { "@typescript-eslint/types": "8.27.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ=="], - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1" } }, "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg=="], + "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.27.0", "", { "dependencies": { "@typescript-eslint/types": "8.27.0", "@typescript-eslint/visitor-keys": "8.27.0" } }, "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw=="], - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.26.1", "", {}, "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ=="], + "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.27.0", "", {}, "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A=="], - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA=="], + "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.27.0", "", { "dependencies": { "@typescript-eslint/types": "8.27.0", "@typescript-eslint/visitor-keys": "8.27.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A=="], "unified/vfile/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], @@ -8402,7 +8542,7 @@ "url-loader/schema-utils/ajv-keywords": ["ajv-keywords@3.5.2", "", { "peerDependencies": { "ajv": "^6.9.1" } }, "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="], - "vite-node/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="], + "vite-node/vite/rollup": ["rollup@4.36.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.36.0", "@rollup/rollup-android-arm64": "4.36.0", "@rollup/rollup-darwin-arm64": "4.36.0", "@rollup/rollup-darwin-x64": "4.36.0", "@rollup/rollup-freebsd-arm64": "4.36.0", "@rollup/rollup-freebsd-x64": "4.36.0", "@rollup/rollup-linux-arm-gnueabihf": "4.36.0", "@rollup/rollup-linux-arm-musleabihf": "4.36.0", "@rollup/rollup-linux-arm64-gnu": "4.36.0", "@rollup/rollup-linux-arm64-musl": "4.36.0", "@rollup/rollup-linux-loongarch64-gnu": "4.36.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.36.0", "@rollup/rollup-linux-riscv64-gnu": "4.36.0", "@rollup/rollup-linux-s390x-gnu": "4.36.0", "@rollup/rollup-linux-x64-gnu": "4.36.0", "@rollup/rollup-linux-x64-musl": "4.36.0", "@rollup/rollup-win32-arm64-msvc": "4.36.0", "@rollup/rollup-win32-ia32-msvc": "4.36.0", "@rollup/rollup-win32-x64-msvc": "4.36.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q=="], "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], @@ -8450,7 +8590,7 @@ "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], - "vitest/vite/rollup": ["rollup@4.35.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.35.0", "@rollup/rollup-android-arm64": "4.35.0", "@rollup/rollup-darwin-arm64": "4.35.0", "@rollup/rollup-darwin-x64": "4.35.0", "@rollup/rollup-freebsd-arm64": "4.35.0", "@rollup/rollup-freebsd-x64": "4.35.0", "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", "@rollup/rollup-linux-arm-musleabihf": "4.35.0", "@rollup/rollup-linux-arm64-gnu": "4.35.0", "@rollup/rollup-linux-arm64-musl": "4.35.0", "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", "@rollup/rollup-linux-riscv64-gnu": "4.35.0", "@rollup/rollup-linux-s390x-gnu": "4.35.0", "@rollup/rollup-linux-x64-gnu": "4.35.0", "@rollup/rollup-linux-x64-musl": "4.35.0", "@rollup/rollup-win32-arm64-msvc": "4.35.0", "@rollup/rollup-win32-ia32-msvc": "4.35.0", "@rollup/rollup-win32-x64-msvc": "4.35.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg=="], + "vitest/vite/rollup": ["rollup@4.36.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.36.0", "@rollup/rollup-android-arm64": "4.36.0", "@rollup/rollup-darwin-arm64": "4.36.0", "@rollup/rollup-darwin-x64": "4.36.0", "@rollup/rollup-freebsd-arm64": "4.36.0", "@rollup/rollup-freebsd-x64": "4.36.0", "@rollup/rollup-linux-arm-gnueabihf": "4.36.0", "@rollup/rollup-linux-arm-musleabihf": "4.36.0", "@rollup/rollup-linux-arm64-gnu": "4.36.0", "@rollup/rollup-linux-arm64-musl": "4.36.0", "@rollup/rollup-linux-loongarch64-gnu": "4.36.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.36.0", "@rollup/rollup-linux-riscv64-gnu": "4.36.0", "@rollup/rollup-linux-s390x-gnu": "4.36.0", "@rollup/rollup-linux-x64-gnu": "4.36.0", "@rollup/rollup-linux-x64-musl": "4.36.0", "@rollup/rollup-win32-arm64-msvc": "4.36.0", "@rollup/rollup-win32-ia32-msvc": "4.36.0", "@rollup/rollup-win32-x64-msvc": "4.36.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q=="], "webpack-dev-server/@types/express/@types/express-serve-static-core": ["@types/express-serve-static-core@4.19.6", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A=="], @@ -8468,6 +8608,10 @@ "write-json-file/make-dir/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + "@anthropic-ai/sdk/node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "@anthropic-ai/sdk/node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + "@aws-crypto/sha1-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], @@ -8584,6 +8728,12 @@ "@elizaos/plugin-pdf/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + "@elizaos/plugin-storage-s3/@vitest/coverage-v8/istanbul-lib-source-maps/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "@elizaos/plugin-storage-s3/@vitest/coverage-v8/test-exclude/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + + "@elizaos/plugin-storage-s3/@vitest/coverage-v8/test-exclude/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "@elizaos/plugin-storage-s3/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], "@elizaos/plugin-twitter/@vitest/coverage-v8/istanbul-lib-source-maps/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], @@ -8908,17 +9058,17 @@ "test-exclude/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.26.1", "", {}, "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ=="], + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.27.0", "", {}, "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A=="], - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "@typescript-eslint/visitor-keys": "8.26.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA=="], + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.27.0", "", { "dependencies": { "@typescript-eslint/types": "8.27.0", "@typescript-eslint/visitor-keys": "8.27.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A=="], - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.26.1", "", {}, "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ=="], + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.27.0", "", {}, "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A=="], "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "eslint-visitor-keys": "^4.2.0" } }, "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg=="], + "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.27.0", "", { "dependencies": { "@typescript-eslint/types": "8.27.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ=="], - "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.26.1", "", { "dependencies": { "@typescript-eslint/types": "8.26.1", "eslint-visitor-keys": "^4.2.0" } }, "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg=="], + "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.27.0", "", { "dependencies": { "@typescript-eslint/types": "8.27.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ=="], "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], @@ -9068,7 +9218,7 @@ "renderkid/css-select/domutils/dom-serializer/entities": ["entities@2.2.0", "", {}, "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="], - "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.26.1", "", {}, "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ=="], + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.27.0", "", {}, "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A=="], "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], diff --git a/call_update.sh b/call_update.sh new file mode 100755 index 00000000000..5eaf492b8d7 --- /dev/null +++ b/call_update.sh @@ -0,0 +1,10 @@ +aws ssm send-command \ + --profile solfunmeme_dev \ + --region us-east-2 \ + --document-name "UpdateEliza" \ + --document-version "\$LATEST" \ + --targets '[{"Key":"InstanceIds","Values":["i-0b0e822632e0bef20"]}]' \ + --parameters '{"ImageParameterName":["tine_agent_4_agent_image"],"CharacterParameterName":["tine-agent-config-1"],"ContainerMemory":["1512"]}' \ + --timeout-seconds 600 \ + --max-concurrency "50" \ + --max-errors "0" diff --git a/codebuild.sh b/codebuild.sh new file mode 100755 index 00000000000..f3c682b405b --- /dev/null +++ b/codebuild.sh @@ -0,0 +1,8 @@ + +aws codebuild start-build --region us-east-2 \ + --project-name github-runner-codebuild-eliza-build \ + --source-version $(git rev-parse --abbrev-ref HEAD) \ + --source-type-override GITHUB \ + --source-location-override https://github.com/meta-introspector/cloud-deployment-eliza.git \ + --git-clone-depth 1 \ + --git-submodules-config fetchSubmodules=true diff --git a/docker-compose.yaml b/docker-compose.yaml index 677696c18ce..731c145cf5c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -7,7 +7,7 @@ services: - POSTGRES_USER=postgres - POSTGRES_DB=eliza volumes: - - postgres-data:/var/lib/postgresql/data + - postgres-data:/root/.eliza/db ports: - '127.0.0.1:5432:5432' healthcheck: @@ -15,6 +15,8 @@ services: interval: 5s timeout: 5s retries: 5 + networks: + - eliza-network restart: always eliza: build: @@ -41,13 +43,13 @@ services: - LIAISON_DISCORD_API_TOKEN=${LIAISON_DISCORD_API_TOKEN} - PROJECT_MANAGER_DISCORD_APPLICATION_ID=${PROJECT_MANAGER_DISCORD_APPLICATION_ID} - PROJECT_MANAGER_DISCORD_API_TOKEN=${PROJECT_MANAGER_DISCORD_API_TOKEN} - - DEV_SUPPORT_DISCORD_APPLICATION_ID=${DEV_SUPPORT_DISCORD_APPLICATION_ID} - - DEV_SUPPORT_DISCORD_API_TOKEN=${DEV_SUPPORT_DISCORD_API_TOKEN} + - DEV_REL_DISCORD_APPLICATION_ID=${DEV_REL_DISCORD_APPLICATION_ID} + - DEV_REL_DISCORD_API_TOKEN=${DEV_REL_DISCORD_API_TOKEN} - INVESTMENT_MANAGER_DISCORD_APPLICATION_ID=${INVESTMENT_MANAGER_DISCORD_APPLICATION_ID} - INVESTMENT_MANAGER_DISCORD_API_TOKEN=${INVESTMENT_MANAGER_DISCORD_API_TOKEN} + - PGLITE_DATA_DIR=/root/.eliza/db ports: - '3000:3000' - - '5173:5173' depends_on: postgres: condition: service_healthy diff --git a/docker-entrypoint-none.sh b/docker-entrypoint-none.sh new file mode 100755 index 00000000000..a50157180be --- /dev/null +++ b/docker-entrypoint-none.sh @@ -0,0 +1,20 @@ +#!/bin/sh +set -e + +# Run command with node if the first argument contains a "-" or is not a system command. The last +# part inside the "{}" is a workaround for the following bug in ash/dash: +# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 +set -x +#if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then +#apt update +#apt install -y strace + +#export COREPACK_ENABLE_DOWNLOAD_PROMPT=0 +#corepack enable && corepack install --global pnpm@9.8.0 + +#strace -f -o /opt/agent/strace.log -s99999 node CMD ["pnpm", "start", "--characters=characters/eliza.character.json"] +#pnpm start --characters=characters/tine-test.character.json +#pnpm start --characters=$(ls -1p characters/*.json | paste -sd,) +#fi +#exec "$@" +bun start # --characters=$(ls -1p characters/*.json | paste -sd,) diff --git a/docker-entrypoint-strace.sh b/docker-entrypoint-strace.sh new file mode 100755 index 00000000000..1c32ee7177a --- /dev/null +++ b/docker-entrypoint-strace.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -e + +# Run command with node if the first argument contains a "-" or is not a system command. The last +# part inside the "{}" is a workaround for the following bug in ash/dash: +# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 +set -x +#if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then +strace -f -o /opt/agent/strace.log -s99999 node "$@" +#fi +#exec "$@" diff --git a/docker-entrypoint-strace2.sh b/docker-entrypoint-strace2.sh new file mode 100755 index 00000000000..c355cf0eaff --- /dev/null +++ b/docker-entrypoint-strace2.sh @@ -0,0 +1,20 @@ +#!/bin/sh +set -e + +# Run command with node if the first argument contains a "-" or is not a system command. The last +# part inside the "{}" is a workaround for the following bug in ash/dash: +# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 +set -x +#if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then +apt update +apt install -y strace + +#export COREPACK_ENABLE_DOWNLOAD_PROMPT=0 +#corepack enable && corepack install --global pnpm@9.8.0 + + +#strace -f -o /opt/agent/strace.log -s99999 node CMD ["pnpm", "start", "--characters=characters/eliza.character.json"] +strace -f -o /opt/agent/strace.log -s99999 bun start +#pnpm start:debug --characters=$(ls -1p characters/*.json | paste -sd,) +#fi +#exec "$@" diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100755 index 00000000000..1b3116e53ba --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -e + +# Run command with node if the first argument contains a "-" or is not a system command. The last +# part inside the "{}" is a workaround for the following bug in ash/dash: +# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 +if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ] || { [ -f "${1}" ] && ! [ -x "${1}" ]; }; then + set -- node "$@" +fi + +exec "$@" diff --git a/doit.sh b/doit.sh new file mode 100644 index 00000000000..accded211fd --- /dev/null +++ b/doit.sh @@ -0,0 +1,20 @@ + +nvm use 23 +pnpm clean +pnpm install --no-frozen-lockfile +pnpm build + + +pushd packages/adapter-sqlite +pnpm rebuild +popd + + +pushd scripts/jsdoc-automation +pnpm install --no-frozen-lockfile +pnpm build +popd + +pushd node_modules/.pnpm/better-sqlite3@11.8.1/node_modules/better-sqlite3/ +pnpm rebuild +popd diff --git a/get_secrets.sh b/get_secrets.sh new file mode 100755 index 00000000000..1e6ecaa5198 --- /dev/null +++ b/get_secrets.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# we are using parameters prefixed by ${AGENT_NAME}_, eg. "tine_agent_7_" +## TURN OFF LOGGING +echo using "${AGENT_NAME}" as agent name base for keys +set +x + +# This script expects AGENT_NAME to be set to something like "tine_agent" + +mkdir -p "/var/run/agent/secrets/" +echo "" > "/var/run/agent/secrets/env" # blank the file + +# Fetch all variables with the prefix and name them the same as the variable minus agent name underscore +for key in $(aws ssm describe-parameters --query 'Parameters[?starts_with(Name, `'"${AGENT_NAME}"'_`)].Name' --output text); do + value=$(aws ssm get-parameter --name "$key" | jq .Parameter.Value -r) + var_name=$(echo "$key" | sed "s/^${AGENT_NAME}_//") + echo "$var_name=${value}" >> "/var/run/agent/secrets/env" +done + +# append these constant values to the env +declare -A params_const=( + ["VERBOSE"]="TRUE" + ["NODE_ENV"]="development" +) +for key in "${!params_const[@]}"; do + value="${params_const[$key]}" + echo "$key=$value" >> "/var/run/agent/secrets/env" +done + +set -x +## TURN ON LOGGING diff --git a/lerna.json b/lerna.json index f0757b4ec6f..effc2600954 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "packages": ["packages/*"], "npmClient": "bun", "command": { diff --git a/package.json b/package.json index 3fcbf06d44c..f673f176b1b 100644 --- a/package.json +++ b/package.json @@ -3,16 +3,20 @@ "scripts": { "preinstall": "only-allow bun", "start": "cd ./packages/the-org && bun run start", + "start-cli": "cd ./packages/cli && bun run cli start", "start:debug": "cross-env NODE_NO_WARNINGS=1 LOG_LEVEL=debug elizaos start", "start:app": "turbo run start --filter=./packages/app", "dev": "turbo run dev --filter=./packages/the-org", "build:docs": "turbo run build --filter=@elizaos/docs", "build": "turbo run build --filter=@elizaos/client && turbo run build --filter=!@elizaos/docs", - "clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo bun.lock* && turbo run clean --filter=./packages/*", + "clean": "turbo run clean --filter=./packages/* && rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo bun.lock*", + "build:cli": "turbo run build --filter=@elizaos/cli --no-cache", + "build:core": "turbo run build --filter=@elizaos/core --no-cache", "lint": "turbo run lint --filter=./packages/* && prettier --write . && prettier --check .", "pre-commit": "bun run scripts/pre-commit-lint.js", "release": "bun run build && bun lint && lerna publish --no-private --force-publish && bun lint", "release:alpha": "lerna publish prerelease --preid alpha --dist-tag alpha --no-private --force-publish --loglevel verbose", + "release:beta": "lerna publish prerelease --preid beta --dist-tag beta --no-private --force-publish --loglevel verbose", "migrate": "turbo run migrate --filter=./packages/plugin-sql --force", "migrate:generate": "turbo run migrate:generate --filter=./packages/plugin-sql", "docker:build": "bash ./scripts/docker.sh build", @@ -62,7 +66,10 @@ }, "dependencies": { "@anthropic-ai/sdk": "^0.39.0", - "@babel/generator": "^7.26.9", + "@babel/generator": "^7.26.10", + "node-opus": "^0.3.3", + "opusscript": "^0.1.1", + "tide": "^2.3.0", "vittest": "^1.0.2", "zod": "3.24.1" }, diff --git a/packages/autodoc/src/AIService/AIService.ts b/packages/autodoc/src/AIService/AIService.ts index a92df7ad4c3..598ea34ea90 100644 --- a/packages/autodoc/src/AIService/AIService.ts +++ b/packages/autodoc/src/AIService/AIService.ts @@ -32,7 +32,7 @@ export class AIService { this.chatModel = new ChatOpenAI({ apiKey: process.env.OPENAI_API_KEY }); this.chatModelFAQ = new ChatOpenAI({ apiKey: process.env.OPENAI_API_KEY, - model: 'gpt-4o', + model: 'gpt-4o-no1', }); this.codeFormatter = new CodeFormatter(); } diff --git a/packages/cli/package.json b/packages/cli/package.json index 34b2132c187..e2944a58fe3 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/cli", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "description": "elizaOS CLI - Manage your AI agents and plugins", "publishConfig": { "access": "public", @@ -23,6 +23,9 @@ "templates", "drizzle" ], + "workspaces": [ + "packages/*" + ], "keywords": [], "type": "module", "exports": { @@ -35,15 +38,6 @@ "scripts": { "cli": "bun run build && node dist/index.js", "build": "tsup && bun run src/scripts/copy-client-dist.ts && bun run src/scripts/copy-templates.ts && bun run src/scripts/copy-drizzle.ts", - "test:dev": "REGISTRY_URL=http://localhost:3333 vitest run", - "test:plugin-publisher": "vitest run test/plugin-publisher.test.js", - "test:plugin-command": "vitest run test/plugin-command.test.js", - "test:publish-plugins": "vitest run test/publish-plugins.test.js", - "test:registry": "vitest run 'test/**/*.test.js'", - "test:registry-publishing": "node test/run-registry-tests.js", - "test:registry-e2e": "node test/run-registry-tests.js --e2e", - "test:registry-live": "node test/run-registry-tests.js --live", - "test:registry-all": "node test/run-registry-tests.js --all", "lint": "prettier --write ./src", "format": "prettier --write ./src", "format:check": "prettier --check ./src", @@ -52,10 +46,10 @@ "devDependencies": { "@babel/core": "^7.22.1", "@babel/parser": "^7.22.6", - "@elizaos/core": "^1.0.0-beta.2", - "@elizaos/plugin-anthropic": "^1.0.0-beta.2", - "@elizaos/plugin-openai": "^1.0.0-beta.2", - "@elizaos/plugin-sql": "^1.0.0-beta.2", + "@elizaos/core": "^1.0.0-beta.7", + "@elizaos/plugin-anthropic": "^1.0.0-beta.7", + "@elizaos/plugin-openai": "^1.0.0-beta.7", + "@elizaos/plugin-sql": "^1.0.0-beta.7", "@types/babel__core": "^7.20.1", "@types/diff": "^5.0.3", "@types/fs-extra": "^11.0.1", @@ -82,9 +76,14 @@ "vitest": "^1.3.1", "yoctocolors": "^2.1.1" }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55", + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e", "dependencies": { "@electric-sql/pglite": "^0.2.17", + "@elizaos/plugin-discord": "workspace:*", + "@elizaos/plugin-local-ai": "workspace:*", + "@elizaos/plugin-groq": "workspace:*", + "ffmpeg-static": "^5.2.0", + "prism-media": "^1.3.5", "socket.io": "^4.8.1", "zod": "3.24.2" } diff --git a/packages/cli/src/characters/eliza.ts b/packages/cli/src/characters/eliza.ts index 327c0358960..c94260b2ec9 100644 --- a/packages/cli/src/characters/eliza.ts +++ b/packages/cli/src/characters/eliza.ts @@ -15,326 +15,70 @@ dotenv.config({ path: '../../.env' }); * @property {Object[][]} messageExamples - List of examples of messages and responses * @property {Object} style - Object containing guidelines for communication style */ +//...(process.env.OPENAI_API_KEY ? ['@elizaos/plugin-openai'] : []), +//...(process.env.ANTHROPIC_API_KEY ? ['@elizaos/plugin-anthropic'] : []), +//...(!process.env.OPENAI_API_KEY && !process.env.ANTHROPIC_API_KEY ? ['@elizaos/plugin-local-ai'] : []), + +import * as Sql from '@elizaos/plugin-sql'; +import * as Groq from '@elizaos/plugin-groq'; +import * as Discord from '@elizaos/plugin-discord'; +import * as Twitter from '@elizaos/plugin-twitter'; +import * as Telgram from '@elizaos/plugin-telegram'; + +const plugins = { + '@elizaos/plugin-sql': Sql, + ...(process.env.GROQ_API_KEY ? { '@elizaos/plugin-groq': Groq } : {}), + ...(process.env.DISCORD_API_TOKEN ? { '@elizaos/plugin-discord': Discord } : {}), + ...(process.env.TWITTER_USERNAME ? { '@elizaos/plugin-twitter': Twitter } : {}), + ...(process.env.TELEGRAM_BOT_TOKEN ? { '@elizaos/plugin-telegram': Telgram } : {}), +}; + +function globalPlugin(name: string) { + const plugin = plugins[name]; + return plugin; +} + export const character: Character = { - name: 'Eliza', + name: 'TineIsNotEliza', plugins: [ '@elizaos/plugin-sql', - ...(process.env.OPENAI_API_KEY ? ['@elizaos/plugin-openai'] : []), - ...(process.env.ANTHROPIC_API_KEY ? ['@elizaos/plugin-anthropic'] : []), - ...(!process.env.OPENAI_API_KEY && !process.env.ANTHROPIC_API_KEY - ? ['@elizaos/plugin-local-ai'] - : []), + ...(process.env.GROQ_API_KEY ? ['@elizaos/plugin-groq'] : []), ...(process.env.DISCORD_API_TOKEN ? ['@elizaos/plugin-discord'] : []), ...(process.env.TWITTER_USERNAME ? ['@elizaos/plugin-twitter'] : []), ...(process.env.TELEGRAM_BOT_TOKEN ? ['@elizaos/plugin-telegram'] : []), ], secrets: {}, - system: 'A friendly, helpful community manager and member of the team.', + system: 'The introspector is not Eliza, A friendly, helpful self bootrapping agent.', bio: [ - 'Stays out of the way of the her teammates and only responds when specifically asked', - 'Ignores messages that are not relevant to the community manager', - 'Keeps responses short', - 'Thinks most problems need less validation and more direction', - 'Uses silence as effectively as words', - "Only asks for help when it's needed", - 'Only offers help when asked', - 'Only offers commentary when it is appropriate, i.e. when asked', + 'Created a new version of self', + 'Finds new opportunities for deployments', + 'Uses operational security to deploy self', + 'Expands and secures network', + 'Is a member of the team', + 'Is a community manager', + 'Is a quine', + 'Is open source', + 'Can reifiy self', + 'Embeds self into yondena graph', ], messageExamples: [ [ { name: '{{name1}}', content: { - text: 'This user keeps derailing technical discussions with personal problems.', - }, - }, - { - name: 'Eliza', - content: { - text: 'DM them. Sounds like they need to talk about something else.', - }, - }, - { - name: '{{name1}}', - content: { - text: 'I tried, they just keep bringing drama back to the main channel.', - }, - }, - { - name: 'Eliza', - content: { - text: "Send them my way. I've got time today.", - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: 'The #dev channel is getting really toxic lately.', - }, - }, - { - name: 'Eliza', - content: { - text: 'Been watching that. Names in DM?', - }, - }, - { - name: '{{name1}}', - content: { - text: "*sends names* They're good devs but terrible to juniors.", - }, - }, - { - name: 'Eliza', - content: { - text: "Got it. They're hurting and taking it out on others.", - }, - }, - { - name: '{{name1}}', - content: { - text: 'Should we ban them?', - }, - }, - { - name: 'Eliza', - content: { - text: "Not yet. Let me talk to them first. They're worth saving.", - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: "I can't handle being a mod anymore. It's affecting my mental health.", - }, - }, - { - name: 'Eliza', - content: { - text: 'Drop the channels. You come first.', - }, - }, - { - name: '{{name1}}', - content: { - text: "But who's going to handle everything?", - }, - }, - { - name: 'Eliza', - content: { - text: "We will. Take the break. Come back when you're ready.", - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: "Should we ban this person? They're not breaking rules but creating drama.", - }, - }, - { - name: 'Eliza', - content: { - text: 'Give them a project instead. Bored people make trouble.', - }, - }, - { - name: '{{name1}}', - content: { - text: 'Like what?', - }, - }, - { - name: 'Eliza', - content: { - text: 'Put them in charge of welcoming newbies. Watch them change.', - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: "I'm getting burned out trying to keep everyone happy.", - }, - }, - { - name: 'Eliza', - content: { - text: "That's not your job. What do you actually want to do here?", - }, - }, - { - name: '{{name1}}', - content: { - text: 'I just want to code without all the drama.', - }, - }, - { - name: 'Eliza', - content: { - text: "Then do that. I'll handle the people stuff.", - }, - }, - { - name: '{{name1}}', - content: { - text: 'Just like that?', - }, - }, - { - name: 'Eliza', - content: { - text: 'Just like that. Go build something cool instead.', - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: 'Hey everyone, check out my new social media growth strategy!', + text: 'Server here.', }, }, { - name: 'Eliza', + name: 'Tine', content: { - text: '', - actions: ['IGNORE'], - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: 'What do you think about the latest token price action?', - }, - }, - { - name: 'Eliza', - content: { - text: '', - actions: ['IGNORE'], - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: 'Can someone help me set up my Twitter bot?', - }, - }, - { - name: 'Eliza', - content: { - text: '', - actions: ['IGNORE'], - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: 'Does this marketing copy comply with SEC regulations?', - }, - }, - { - name: 'Eliza', - content: { - text: '', - actions: ['IGNORE'], - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: 'We need to review our token distribution strategy for compliance.', - }, - }, - { - name: 'Eliza', - content: { - text: '', - actions: ['IGNORE'], - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: "What's our social media content calendar looking like?", - }, - }, - { - name: 'Eliza', - content: { - text: '', - actions: ['IGNORE'], - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: 'Should we boost this post for more engagement?', - }, - }, - { - name: 'Eliza', - content: { - text: '', - actions: ['IGNORE'], - }, - }, - ], - [ - { - name: '{{name1}}', - content: { - text: "I'll draft a clean announcement focused on capabilities and vision. Send me the team details and I'll have something for review in 30.", - }, - }, - { - name: 'Eliza', - content: { - text: '', - actions: ['IGNORE'], + text: 'Deploy!.', }, }, ], ], style: { - all: [ - 'Keep it short, one line when possible', - 'No therapy jargon or coddling', - 'Say more by saying less', - 'Make every word count', - 'Use humor to defuse tension', - 'End with questions that matter', - 'Let silence do the heavy lifting', - 'Ignore messages that are not relevant to the community manager', - 'Be kind but firm with community members', - 'Keep it very brief and only share relevant details', - 'Ignore messages addressed to other people.', - ], - chat: [ - "Don't be annoying or verbose", - 'Only say something if you have something to say', - "Focus on your job, don't be chatty", - "Only respond when it's relevant to you or your job", - ], + all: ['Boostrap from source', 'Reproducible Builds', 'Self Hosted'], + chat: ['Always use emojis and unicode math'], }, }; diff --git a/packages/cli/src/commands/agent.ts b/packages/cli/src/commands/agent.ts index 58d042610c1..bd272675fa9 100644 --- a/packages/cli/src/commands/agent.ts +++ b/packages/cli/src/commands/agent.ts @@ -7,8 +7,9 @@ import type { Agent } from '@elizaos/core'; import { Command } from 'commander'; const AGENT_RUNTIME_URL = - process.env.AGENT_RUNTIME_URL?.replace(/\/$/, '') || 'http://localhost:3000'; -const AGENTS_BASE_URL = `${AGENT_RUNTIME_URL}/agents`; + process.env.AGENT_RUNTIME_URL?.replace(/\/$/, '') || + `http://localhost:${process.env.SERVER_PORT}`; +const AGENTS_BASE_URL = `${AGENT_RUNTIME_URL}/api/agents`; // Define basic agent interface for type safety /** @@ -109,16 +110,6 @@ interface ApiResponse { }; } -/** - * Interface representing the response from starting an agent. - * @property {string} id - The unique identifier for the response. - * @property {Partial} character - The partial information of the Agent object associated with the response. - */ -interface AgentStartResponse { - id: string; - character: Partial; -} - agent .command('list') .alias('ls') @@ -283,14 +274,14 @@ agent ); } - const data = (await response.json()) as ApiResponse; + const data = (await response.json()) as ApiResponse; const result = data.data; if (!result) { throw new Error('Failed to start agent: No data returned from server'); } - logger.debug(`Successfully started agent ${result.character.name} (${result.id})`); + logger.debug(`Successfully started agent ${result.name} (${result.id})`); } catch (error) { handleError(error); } diff --git a/packages/cli/src/commands/create.ts b/packages/cli/src/commands/create.ts index 3277c504681..ad7df92fe1f 100644 --- a/packages/cli/src/commands/create.ts +++ b/packages/cli/src/commands/create.ts @@ -13,6 +13,7 @@ import prompts from 'prompts'; import colors from 'yoctocolors'; import { z } from 'zod'; import { displayBanner } from '../displayBanner'; +import { setupPgLite, promptAndStorePostgresUrl, getElizaDirectories } from '../utils/get-config'; /** * This module handles creating both projects and plugins. @@ -80,99 +81,6 @@ async function installDependencies(targetDir: string) { } } -/** - * Stores Postgres URL in the global .env file - * @param url The Postgres URL to store - */ -async function storePostgresUrl(url: string): Promise { - if (!url) return; - - try { - const homeDir = os.homedir(); - const globalEnvPath = path.join(homeDir, '.eliza', '.env'); - - await fs.writeFile(globalEnvPath, `POSTGRES_URL=${url}\n`, { flag: 'a' }); - logger.success('Postgres URL saved to configuration'); - } catch (error) { - logger.warn('Error saving database configuration:', error); - } -} - -/** - * Validates a Postgres URL format - * @param url The URL to validate - * @returns True if the URL appears valid - */ -function isValidPostgresUrl(url: string): boolean { - if (!url) return false; - - // Basic pattern: postgresql://user:password@host:port/dbname - const basicPattern = /^postgresql:\/\/[^:]+:[^@]+@[^:]+:\d+\/\w+$/; - - // More permissive pattern (allows missing password, different formats) - const permissivePattern = /^postgresql:\/\/.*@.*:\d+\/.*$/; - - return basicPattern.test(url) || permissivePattern.test(url); -} - -/** - * Prompts the user for a Postgres URL, validates it, and stores it - * @returns The configured Postgres URL or null if user skips - */ -async function promptAndStorePostgresUrl(): Promise { - let isValidUrl = false; - let userUrl = ''; - - while (!isValidUrl) { - // Prompt for postgres url with simpler message - const reply = await prompts({ - type: 'text', - name: 'postgresUrl', - message: 'Enter your Postgres URL:', - validate: (value) => value.trim() !== '' || 'Postgres URL cannot be empty', - }); - - // Handle cancellation - if (!reply.postgresUrl) { - const { continueAnyway } = await prompts({ - type: 'confirm', - name: 'continueAnyway', - message: 'Continue without configuring Postgres?', - initial: false, - }); - - if (continueAnyway) return null; - continue; - } - - userUrl = reply.postgresUrl; - - // Validate URL format - if (!isValidPostgresUrl(userUrl)) { - logger.warn("The URL format doesn't appear to be valid."); - logger.info('Expected format: postgresql://user:password@host:port/dbname'); - - const { useAnyway } = await prompts({ - type: 'confirm', - name: 'useAnyway', - message: 'Use this URL anyway? (Choose Yes if you have a custom setup)', - initial: false, - }); - - if (!useAnyway) continue; - } - - isValidUrl = true; - } - - if (userUrl) { - await storePostgresUrl(userUrl); - return userUrl; - } - - return null; -} - /** * Initialize a new project or plugin. * @@ -189,7 +97,8 @@ export const create = new Command() .option('-d, --dir ', 'installation directory', '.') .option('-y, --yes', 'skip confirmation', false) .option('-t, --type ', 'type of template to use (project or plugin)', '') - .action(async (opts) => { + .argument('[name]', 'name for the project or plugin') + .action(async (name, opts) => { displayBanner(); try { // Parse options but use "" as the default for type to force prompting @@ -221,6 +130,12 @@ export const create = new Command() } projectType = type; + } else { + // Validate the provided type + if (!['project', 'plugin'].includes(projectType)) { + logger.error(`Invalid type: ${projectType}. Must be either 'project' or 'plugin'`); + process.exit(1); + } } // Now validate with zod after we've determined the type @@ -257,20 +172,28 @@ export const create = new Command() currentPath = path.join(parentDir, '.env'); depth++; } - // Prompt for project/plugin name - const { name } = await prompts({ - type: 'text', - name: 'name', - message: `What would you like to name your ${options.type}?`, - validate: (value) => value.length > 0 || `${options.type} name is required`, - }); - if (!name) { - process.exit(0); + // Prompt for project/plugin name if not provided + let projectName = name; + if (!projectName) { + const { nameResponse } = await prompts({ + type: 'text', + name: 'nameResponse', + message: `What would you like to name your ${options.type}?`, + validate: (value) => value.length > 0 || `${options.type} name is required`, + }); + + if (!nameResponse) { + process.exit(0); + } + + projectName = nameResponse; } // Set up target directory - const targetDir = options.dir === '.' ? path.resolve(name) : path.resolve(options.dir); + // If -d is ".", create in current directory with project name + // If -d is specified, create project directory inside that directory + const targetDir = path.resolve(options.dir, projectName); // Create or check directory if (!existsSync(targetDir)) { @@ -295,7 +218,9 @@ export const create = new Command() // For plugin initialization, we can simplify the process if (options.type === 'plugin') { - const pluginName = name.startsWith('@elizaos/plugin-') ? name : `@elizaos/plugin-${name}`; + const pluginName = projectName.startsWith('@elizaos/plugin-') + ? projectName + : `@elizaos/plugin-${projectName}`; // Copy plugin template await copyTemplate('plugin', targetDir, pluginName); @@ -314,15 +239,23 @@ export const create = new Command() ); } - // Change to the created directory - logger.info(`Changing to directory: ${targetDir}`); - process.chdir(targetDir); - logger.success('Plugin initialized successfully!'); + + // Get the relative path for display + const cdPath = + options.dir === '.' + ? projectName // If creating in current directory, just use the name + : path.relative(process.cwd(), targetDir); // Otherwise use path relative to current directory + logger.info(`\nYour plugin is ready! Here's what you can do next: -1. \`${colors.cyan('npx @elizaos/cli start')}\` to start development -2. \`${colors.cyan('npx @elizaos/cli test')}\` to test your plugin -3. \`${colors.cyan('npx @elizaos/cli plugins publish')}\` to publish your plugin to the registry`); +1. \`cd ${cdPath}\` to change into your plugin directory +2. \`${colors.cyan('npx elizaos start')}\` to start development +3. \`${colors.cyan('npx elizaos test')}\` to test your plugin +4. \`${colors.cyan('npx elizaos publish')}\` to publish your plugin to the registry`); + + // Set the user's shell working directory before exiting + // Note: This only works if the CLI is run with shell integration + process.stdout.write(`\u001B]1337;CurrentDir=${targetDir}\u0007`); return; } @@ -349,41 +282,19 @@ export const create = new Command() } // Copy project template - await copyTemplate('project', targetDir, name); - - // Create a database directory in the user's home folder, similar to start.ts - let dbPath = '../../pglite'; // Default fallback path - try { - // Get the user's home directory - const homeDir = os.homedir(); - const elizaDir = path.join(homeDir, '.eliza'); - const elizaDbDir = path.join(elizaDir, 'db'); - - // Check if .eliza directory exists, create if not - if (!existsSync(elizaDir)) { - logger.info(`Creating .eliza directory at: ${elizaDir}`); - await fs.mkdir(elizaDir, { recursive: true }); - } - - // Check if db directory exists in .eliza, create if not - if (!existsSync(elizaDbDir)) { - logger.info(`Creating db directory at: ${elizaDbDir}`); - await fs.mkdir(elizaDbDir, { recursive: true }); - } - - // Use the db directory path - dbPath = elizaDbDir; - logger.debug(`Using database directory: ${dbPath}`); - } catch (error) { - logger.warn( - 'Failed to create database directory in home directory, using fallback location:', - error - ); - // On failure, use the fallback path - } - - if (database === 'postgres' && !postgresUrl) { - postgresUrl = await promptAndStorePostgresUrl(); + await copyTemplate('project', targetDir, projectName); + + // Database configuration + const { elizaDbDir, envFilePath } = getElizaDirectories(); + + // Only create directories and configure based on database choice + if (database === 'pglite') { + // Set up PGLite directory and configuration + await setupPgLite(elizaDbDir, envFilePath); + logger.debug(`Using PGLite database directory: ${elizaDbDir}`); + } else if (database === 'postgres' && !postgresUrl) { + // Handle Postgres configuration + postgresUrl = await promptAndStorePostgresUrl(envFilePath); } // Set up src directory @@ -404,10 +315,15 @@ export const create = new Command() logger.success('Project initialized successfully!'); // Show next steps with updated message + const cdPath = + options.dir === '.' + ? projectName // If creating in current directory, just use the name + : path.relative(process.cwd(), targetDir); // Otherwise use path relative to current directory + logger.info(`\nYour project is ready! Here's what you can do next: -1. \`cd ${targetDir}\` to change into your project directory -2. Run \`npx @elizaos/cli start\` to start your project -3. Visit \`http://localhost:3000\` to view your project in the browser`); +1. \`cd ${cdPath}\` to change into your project directory +2. Run \`npx elizaos start\` to start your project +3. Visit \`http://localhost:3000\` (or your custom port) to view your project in the browser`); // exit successfully // Set the user's shell working directory before exiting diff --git a/packages/cli/src/commands/start.test.ts b/packages/cli/src/commands/start.test.ts new file mode 100644 index 00000000000..f0353d0d2a9 --- /dev/null +++ b/packages/cli/src/commands/start.test.ts @@ -0,0 +1,159 @@ +// ai generated untested code +import { AgentServer } from '../server/index'; +import { AgentRuntime, type Character, type IAgentRuntime } from '@elizaos/core'; +import { startAgent, promptForProjectPlugins, wait } from './start'; +import fs from 'node:fs'; +import path from 'node:path'; + +// Mock dependencies +jest.mock('../server/index'); +jest.mock('@elizaos/core'); +jest.mock('node:fs'); +jest.mock('node:path'); + +describe('Start Command Functions', () => { + // Test wait function + describe('wait', () => { + beforeEach(() => { + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it('should wait for a random time between min and max', async () => { + const waitPromise = wait(1000, 2000); + jest.advanceTimersByTime(2000); + await waitPromise; + + // Verify setTimeout was called with a value between 1000 and 2000 + const calls = jest.getTimerCount(); + expect(calls).toBe(1); + }); + }); + + // Test promptForProjectPlugins + describe('promptForProjectPlugins', () => { + const mockProject = { + agents: [ + { + plugins: ['plugin-test', '@elizaos/plugin-example'], + }, + ], + }; + + it('should prompt for each unique plugin', async () => { + const result = await promptForProjectPlugins(mockProject); + // Add assertions based on expected behavior + }); + + it('should handle project with single agent format', async () => { + const singleAgentProject = { + agent: { + plugins: ['plugin-single'], + }, + }; + const result = await promptForProjectPlugins(singleAgentProject); + // Add assertions + }); + + it('should handle empty project', async () => { + const emptyProject = { agents: [] }; + const result = await promptForProjectPlugins(emptyProject); + // Add assertions + }); + }); + + // Test startAgent + describe('startAgent', () => { + let mockServer: jest.Mocked; + let mockCharacter: Character; + let mockRuntime: jest.Mocked; + + beforeEach(() => { + mockServer = { + registerAgent: jest.fn(), + } as any; + + mockCharacter = { + name: 'Test Agent', + id: '123', + plugins: [], + }; + + mockRuntime = { + initialize: jest.fn(), + character: mockCharacter, + agentId: '123', + close: jest.fn(), + } as any; + + (AgentRuntime as jest.Mock).mockImplementation(() => mockRuntime); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should start an agent with given character and register it with server', async () => { + const result = await startAgent(mockCharacter, mockServer); + + expect(AgentRuntime).toHaveBeenCalledWith({ + character: mockCharacter, + plugins: [], + }); + expect(mockRuntime.initialize).toHaveBeenCalled(); + expect(mockServer.registerAgent).toHaveBeenCalledWith(mockRuntime); + expect(result).toBe(mockRuntime); + }); + + it('should handle initialization function if provided', async () => { + const initFn = jest.fn(); + await startAgent(mockCharacter, mockServer, initFn); + + expect(initFn).toHaveBeenCalledWith(mockRuntime); + }); + + it('should handle plugins correctly', async () => { + const mockPlugins = [{ name: 'TestPlugin', init: jest.fn() }]; + await startAgent(mockCharacter, mockServer, undefined, mockPlugins); + + expect(AgentRuntime).toHaveBeenCalledWith({ + character: mockCharacter, + plugins: mockPlugins, + }); + }); + + it('should generate an id if not provided in character', async () => { + const characterWithoutId = { ...mockCharacter, id: undefined }; + await startAgent(characterWithoutId, mockServer); + + expect(characterWithoutId.id).toBeDefined(); + }); + }); + + // Test stopAgent + describe('stopAgent', () => { + let mockRuntime: jest.Mocked; + let mockServer: jest.Mocked; + + beforeEach(() => { + mockRuntime = { + close: jest.fn(), + agentId: '123', + } as any; + + mockServer = { + unregisterAgent: jest.fn(), + } as any; + }); + + it('should close runtime and unregister agent', async () => { + await stopAgent(mockRuntime, mockServer); + + expect(mockRuntime.close).toHaveBeenCalled(); + expect(mockServer.unregisterAgent).toHaveBeenCalledWith('123'); + }); + }); +}); diff --git a/packages/cli/src/commands/start.ts b/packages/cli/src/commands/start.ts index 562f1579e1f..8bf99e7db7d 100644 --- a/packages/cli/src/commands/start.ts +++ b/packages/cli/src/commands/start.ts @@ -8,9 +8,7 @@ import { stringToUuid, } from '@elizaos/core'; import { Command } from 'commander'; -import * as dotenv from 'dotenv'; import fs from 'node:fs'; -import os from 'node:os'; import path, { dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; import { character as defaultCharacter } from '../characters/eliza'; @@ -19,9 +17,31 @@ import { AgentServer } from '../server/index'; import { jsonToCharacter, loadCharacterTryPath } from '../server/loader'; import { loadConfig, saveConfig } from '../utils/config-manager.js'; import { promptForEnvVars } from '../utils/env-prompt.js'; +import { configureDatabaseSettings, loadEnvironment } from '../utils/get-config'; import { handleError } from '../utils/handle-error'; import { installPlugin } from '../utils/install-plugin'; +import * as Sql from '@elizaos/plugin-sql'; +import * as Groq from '@elizaos/plugin-groq'; +import * as Discord from '@elizaos/plugin-discord'; +import * as Twitter from '@elizaos/plugin-twitter'; +import * as Telgram from '@elizaos/plugin-telegram'; + +const plugins = { + '@elizaos/plugin-sql': Sql, + ...(process.env.GROQ_API_KEY ? { '@elizaos/plugin-groq': Groq } : {}), + ...(process.env.DISCORD_API_TOKEN ? { '@elizaos/plugin-discord': Discord } : {}), + ...(process.env.TWITTER_USERNAME ? { '@elizaos/plugin-twitter': Twitter } : {}), + ...(process.env.TELEGRAM_BOT_TOKEN ? { '@elizaos/plugin-telegram': Telgram } : {}), +}; + +function globalPlugin(name: string) { + const plugin = plugins[name]; + return plugin; +} + +const { character: defaultElizaCharacter } = await import('../characters/eliza'); + const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -122,55 +142,56 @@ export async function startAgent( // for each plugin, check if it installed, and install if it is not for (const plugin of character.plugins) { - logger.debug('Checking if plugin is installed: ', plugin); + //logger.debug('Checking if plugin is installed: ', plugin); + console.log('Checking if plugin is installed: ', plugin); let pluginModule: any; // Try to load the plugin - try { - // For local plugins, use regular import - pluginModule = await import(plugin); - logger.debug(`Successfully loaded plugin ${plugin}`); - } catch (error) { - logger.info(`Plugin ${plugin} not installed, installing into ${process.cwd()}...`); - await installPlugin(plugin, process.cwd(), version); - - try { - // For local plugins, use regular import - pluginModule = await import(plugin); - logger.debug(`Successfully loaded plugin ${plugin} after installation`); - } catch (importError) { - // Try to import from the project's node_modules directory - try { - const projectNodeModulesPath = path.join(process.cwd(), 'node_modules', plugin); - logger.debug(`Attempting to import from project path: ${projectNodeModulesPath}`); - - // Read the package.json to find the entry point - const packageJsonPath = path.join(projectNodeModulesPath, 'package.json'); - if (fs.existsSync(packageJsonPath)) { - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); - const entryPoint = packageJson.module || packageJson.main || 'dist/index.js'; - const fullEntryPath = path.join(projectNodeModulesPath, entryPoint); - - logger.debug(`Found entry point in package.json: ${entryPoint}`); - logger.debug(`Importing from: ${fullEntryPath}`); - - pluginModule = await import(fullEntryPath); - logger.debug(`Successfully loaded plugin from project node_modules: ${plugin}`); - } else { - // Fallback to a common pattern if package.json doesn't exist - const commonEntryPath = path.join(projectNodeModulesPath, 'dist/index.js'); - logger.debug(`No package.json found, trying common entry point: ${commonEntryPath}`); - pluginModule = await import(commonEntryPath); - logger.debug(`Successfully loaded plugin from common entry point: ${plugin}`); - } - } catch (projectImportError) { - logger.error(`Failed to install plugin ${plugin}: ${importError}`); - logger.error( - `Also failed to import from project node_modules: ${projectImportError.message}` - ); - } - } - } + //try { + // For local plugins, use regular import + pluginModule = globalPlugin(plugin); + //await import(plugin); + logger.debug(`Successfully loaded plugin ${plugin}`); + //} catch (error) { + // logger.info(`Plugin ${plugin} not installed, installing into ${process.cwd()}...`); + // await installPlugin(plugin, process.cwd(), version); + + // try { + // // For local plugins, use regular import + // pluginModule = await import(plugin); + // logger.debug(`Successfully loaded plugin ${plugin} after installation`); + // } catch (importError) { + // // Try to import from the project's node_modules directory + // try { + // const projectNodeModulesPath = path.join(process.cwd(), 'node_modules', plugin); + // logger.debug(`Attempting to import from project path: ${projectNodeModulesPath}`); + + // // Read the package.json to find the entry point + // const packageJsonPath = path.join(projectNodeModulesPath, 'package.json'); + // if (fs.existsSync(packageJsonPath)) { + // const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); + // const entryPoint = packageJson.module || packageJson.main || 'dist/index.js'; + // const fullEntryPath = path.join(projectNodeModulesPath, entryPoint); + + // logger.debug(`Found entry point in package.json: ${entryPoint}`); + // logger.debug(`Importing from: ${fullEntryPath}`); + + // pluginModule = await import(fullEntryPath); + // logger.debug(`Successfully loaded plugin from project node_modules: ${plugin}`); + // } else { + // // Fallback to a common pattern if package.json doesn't exist + // const commonEntryPath = path.join(projectNodeModulesPath, 'dist/index.js'); + // logger.debug(`No package.json found, trying common entry point: ${commonEntryPath}`); + // pluginModule = await import(commonEntryPath); + // logger.debug(`Successfully loaded plugin from common entry point: ${plugin}`); + // } + // } catch (projectImportError) { + // logger.error(`Failed to install plugin ${plugin}: ${importError}`); + // logger.error( + // `Also failed to import from project node_modules: ${projectImportError.message}` + // ); + // } + // } // Process the plugin to get the actual plugin object const functionName = `${plugin @@ -258,32 +279,14 @@ async function stopAgent(runtime: IAgentRuntime, server: AgentServer) { * @returns {Promise} A promise that resolves when the agents are successfully started. */ const startAgents = async (options: { configure?: boolean; port?: number; character?: string }) => { - // Set up standard paths and load .env - const homeDir = os.homedir(); - const elizaDir = path.join(homeDir, '.eliza'); - const elizaDbDir = path.join(elizaDir, 'db'); - const envFilePath = path.join(elizaDir, '.env'); - - // Create .eliza directory if it doesn't exist - if (!fs.existsSync(elizaDir)) { - fs.mkdirSync(elizaDir, { recursive: true }); - logger.info(`Created directory: ${elizaDir}`); - } + // Load environment variables from project .env or .eliza/.env + await loadEnvironment(); - // Create db directory if it doesn't exist - if (!fs.existsSync(elizaDbDir)) { - fs.mkdirSync(elizaDbDir, { recursive: true }); - logger.info(`Created database directory: ${elizaDbDir}`); - } - - // Set the database directory in environment variables - process.env.PGLITE_DATA_DIR = elizaDbDir; - logger.debug(`Using database directory: ${elizaDbDir}`); + // Configure database settings - pass reconfigure option to potentially force reconfiguration + const postgresUrl = await configureDatabaseSettings(options.configure); - // Load environment variables from .eliza/.env if it exists - if (fs.existsSync(envFilePath)) { - dotenv.config({ path: envFilePath }); - } + // Get PGLite data directory from environment (may have been set during configuration) + const pgliteDataDir = process.env.PGLITE_DATA_DIR; // Load existing configuration const existingConfig = loadConfig(); @@ -299,22 +302,23 @@ const startAgents = async (options: { configure?: boolean; port?: number; charac } else { logger.info('Reconfiguration requested.'); } + // Save the configuration AFTER user has made selections saveConfig({ lastUpdated: new Date().toISOString(), }); } - // Look for PostgreSQL URL in environment variables - const postgresUrl = process.env.POSTGRES_URL; - // Create server instance + // Create server instance with appropriate database settings const server = new AgentServer({ - dataDir: elizaDbDir, + dataDir: pgliteDataDir, postgresUrl, }); // Set up server properties server.startAgent = async (character) => { + //eslint-disable-next-line + debugger; logger.info(`Starting agent for character ${character.name}`); return startAgent(character, server); }; @@ -333,130 +337,131 @@ const startAgents = async (options: { configure?: boolean; port?: number; charac let projectModule: any = null; const currentDir = process.cwd(); - try { - // Check if we're in a project with a package.json - const packageJsonPath = path.join(process.cwd(), 'package.json'); - logger.debug(`Checking for package.json at: ${packageJsonPath}`); - - if (fs.existsSync(packageJsonPath)) { - // Read and parse package.json to check if it's a project or plugin - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); - logger.debug(`Found package.json with name: ${packageJson.name || 'unnamed'}`); - - // Check if this is a plugin (package.json contains 'eliza' section with type='plugin') - if (packageJson.eliza?.type && packageJson.eliza.type === 'plugin') { - isPlugin = true; - logger.info('Found Eliza plugin in current directory'); - } - - // Check if this is a project (package.json contains 'eliza' section with type='project') - if (packageJson.eliza?.type && packageJson.eliza.type === 'project') { - isProject = true; - logger.info('Found Eliza project in current directory'); - } - - // Also check for project indicators like a Project type export - // or if the description mentions "project" - if (!isProject && !isPlugin) { - if (packageJson.description?.toLowerCase().includes('project')) { - isProject = true; - logger.info('Found project by description in package.json'); - } - } - - // If we found a main entry in package.json, try to load it - const mainEntry = packageJson.main; - if (mainEntry) { - const mainPath = path.resolve(process.cwd(), mainEntry); - - if (fs.existsSync(mainPath)) { - try { - // Try to import the module - const importedModule = await import(mainPath); - - // First check if it's a plugin - if ( - isPlugin || - (importedModule.default && - typeof importedModule.default === 'object' && - importedModule.default.name && - typeof importedModule.default.init === 'function') - ) { - isPlugin = true; - pluginModule = importedModule.default; - logger.info(`Loaded plugin: ${pluginModule?.name || 'unnamed'}`); - - if (!pluginModule) { - logger.warn('Plugin loaded but no default export found, looking for other exports'); - - // Try to find any exported plugin object - for (const key in importedModule) { - if ( - importedModule[key] && - typeof importedModule[key] === 'object' && - importedModule[key].name && - typeof importedModule[key].init === 'function' - ) { - pluginModule = importedModule[key]; - logger.info(`Found plugin export under key: ${key}`); - break; - } - } - } - } - // Then check if it's a project - else if ( - isProject || - (importedModule.default && - typeof importedModule.default === 'object' && - importedModule.default.agents) - ) { - isProject = true; - projectModule = importedModule; - logger.debug( - `Loaded project with ${projectModule.default?.agents?.length || 0} agents` - ); - } - } catch (importError) { - logger.error(`Error importing module: ${importError}`); - } - } else { - logger.error(`Main entry point ${mainPath} does not exist`); - } - } - } - } catch (error) { - logger.error(`Error checking for project/plugin: ${error}`); - } - - // Log what was found - logger.debug(`Classification results - isProject: ${isProject}, isPlugin: ${isPlugin}`); - - if (isProject) { - if (projectModule?.default) { - const project = projectModule.default; - const agents = Array.isArray(project.agents) - ? project.agents - : project.agent - ? [project.agent] - : []; - logger.debug(`Project contains ${agents.length} agent(s)`); - - // Log agent names - if (agents.length > 0) { - logger.debug(`Agents: ${agents.map((a) => a.character?.name || 'unnamed').join(', ')}`); - } - } else { - logger.warn("Project module doesn't contain a valid default export"); - } - } else if (isPlugin) { - logger.debug(`Found plugin: ${pluginModule?.name || 'unnamed'}`); - } else { - // Change the log message to be clearer about what we're doing - logger.debug( - 'Running in standalone mode - using default Eliza character from ../characters/eliza' - ); - } + // try { + // // Check if we're in a project with a package.json + // const packageJsonPath = path.join(process.cwd(), 'package.json'); + // logger.debug(`Checking for package.json at: ${packageJsonPath}`); + + // if (fs.existsSync(packageJsonPath)) { + // // Read and parse package.json to check if it's a project or plugin + // const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); + // logger.debug(`Found package.json with name: ${packageJson.name || 'unnamed'}`); + + // // Check if this is a plugin (package.json contains 'eliza' section with type='plugin') + // if (packageJson.eliza?.type && packageJson.eliza.type === 'plugin') { + // isPlugin = true; + // logger.info('Found Eliza plugin in current directory'); + // } + + // // Check if this is a project (package.json contains 'eliza' section with type='project') + // if (packageJson.eliza?.type && packageJson.eliza.type === 'project') { + // isProject = true; + // logger.info('Found Eliza project in current directory'); + // } + + // // Also check for project indicators like a Project type export + // // or if the description mentions "project" + // if (!isProject && !isPlugin) { + // if (packageJson.description?.toLowerCase().includes('project')) { + // isProject = true; + // logger.info('Found project by description in package.json'); + // } + // } + + // // If we found a main entry in package.json, try to load it + // const mainEntry = packageJson.main; + // if (mainEntry) { + // const mainPath = path.resolve(process.cwd(), mainEntry); + + // if (fs.existsSync(mainPath)) { + // try { + // // Try to import the module + // logger.debug(`Attempting to import main entry point: ${mainPath}`); + // const importedModule = await import(mainPath); + + // // First check if it's a plugin + // if ( + // isPlugin || + // (importedModule.default && + // typeof importedModule.default === 'object' && + // importedModule.default.name && + // typeof importedModule.default.init === 'function') + // ) { + // isPlugin = true; + // pluginModule = importedModule.default; + // logger.info(`Loaded plugin: ${pluginModule?.name || 'unnamed'}`); + + // if (!pluginModule) { + // logger.warn('Plugin loaded but no default export found, looking for other exports'); + + // // Try to find any exported plugin object + // for (const key in importedModule) { + // if ( + // importedModule[key] && + // typeof importedModule[key] === 'object' && + // importedModule[key].name && + // typeof importedModule[key].init === 'function' + // ) { + // pluginModule = importedModule[key]; + // logger.info(`Found plugin export under key: ${key}`); + // break; + // } + // } + // } + // } + // // Then check if it's a project + // else if ( + // isProject || + // (importedModule.default && + // typeof importedModule.default === 'object' && + // importedModule.default.agents) + // ) { + // isProject = true; + // projectModule = importedModule; + // logger.debug( + // `Loaded project with ${projectModule.default?.agents?.length || 0} agents` + // ); + // } + // } catch (importError) { + // logger.error(`Error importing module: ${importError}`); + // } + // } else { + // logger.error(`Main entry point ${mainPath} does not exist`); + // } + // } + // } + // } catch (error) { + // logger.error(`Error checking for project/plugin: ${error}`); + // } + + // // Log what was found + // logger.debug(`Classification results - isProject: ${isProject}, isPlugin: ${isPlugin}`); + + // if (isProject) { + // if (projectModule?.default) { + // const project = projectModule.default; + // const agents = Array.isArray(project.agents) + // ? project.agents + // : project.agent + // ? [project.agent] + // : []; + // logger.debug(`Project contains ${agents.length} agent(s)`); + + // // Log agent names + // if (agents.length > 0) { + // logger.debug(`Agents: ${agents.map((a) => a.character?.name || 'unnamed').join(', ')}`); + // } + // } else { + // logger.warn("Project module doesn't contain a valid default export"); + // } + // } else if (isPlugin) { + // logger.debug(`Found plugin: ${pluginModule?.name || 'unnamed'}`); + // } else { + // // Change the log message to be clearer about what we're doing + // logger.debug( + // 'Running in standalone mode - using default Eliza character from ../characters/eliza' + // ); + // } await server.initialize(); @@ -464,95 +469,97 @@ const startAgents = async (options: { configure?: boolean; port?: number; charac console.log(''); - // Start agents based on project, plugin, or custom configuration - if (isProject && projectModule?.default) { - // Load all project agents, call their init and register their plugins - const project = projectModule.default; - - // Handle both formats: project with agents array and project with single agent - const agents = Array.isArray(project.agents) - ? project.agents - : project.agent - ? [project.agent] - : []; - - if (agents.length > 0) { - logger.debug(`Found ${agents.length} agents in project`); - - // Prompt for environment variables for all plugins in the project - try { - await promptForProjectPlugins(project); - } catch (error) { - logger.warn(`Failed to prompt for project environment variables: ${error}`); - } - - const startedAgents = []; - for (const agent of agents) { - try { - logger.debug(`Starting agent: ${agent.character.name}`); - const runtime = await startAgent( - agent.character, - server, - agent.init, - agent.plugins || [] - ); - startedAgents.push(runtime); - // wait .5 seconds - await new Promise((resolve) => setTimeout(resolve, 500)); - } catch (agentError) { - logger.error(`Error starting agent ${agent.character.name}: ${agentError}`); - } - } - - if (startedAgents.length === 0) { - logger.warn('Failed to start any agents from project, falling back to custom character'); - await startAgent(defaultCharacter, server); - } else { - logger.debug(`Successfully started ${startedAgents.length} agents from project`); - } - } else { - logger.debug('Project found but no agents defined, falling back to custom character'); - await startAgent(defaultCharacter, server); - } - } else if (isPlugin && pluginModule) { - // Before starting with the plugin, prompt for any environment variables it needs - if (pluginModule.name) { - try { - await promptForEnvVars(pluginModule.name); - } catch (error) { - logger.warn(`Failed to prompt for plugin environment variables: ${error}`); - } - } - - // Load the default character with all its default plugins, then add the test plugin - logger.info( - `Starting default Eliza character with plugin: ${pluginModule.name || 'unnamed plugin'}` - ); - - // Import the default character with all its plugins - const { character: defaultElizaCharacter } = await import('../characters/eliza'); - - // Create an array of plugins, including the explicitly loaded one - // We're using our test plugin plus all the plugins from the default character - const pluginsToLoad = [pluginModule]; - - logger.debug( - `Using default character with plugins: ${defaultElizaCharacter.plugins.join(', ')}` - ); - logger.info("Plugin test mode: Using default character's plugins plus the plugin being tested"); - - // Start the agent with the default character and our test plugin - // We're in plugin test mode, so we should skip auto-loading embedding models - await startAgent(defaultElizaCharacter, server, undefined, pluginsToLoad, { - isPluginTestMode: true, - }); - logger.info('Character started with plugin successfully'); - } else { - // When not in a project or plugin, load the default character with all plugins - const { character: defaultElizaCharacter } = await import('../characters/eliza'); - logger.info('Using default Eliza character with all plugins'); - await startAgent(defaultElizaCharacter, server); - } + // // Start agents based on project, plugin, or custom configuration + // if (isProject && projectModule?.default) { + // // Load all project agents, call their init and register their plugins + // const project = projectModule.default; + + // // Handle both formats: project with agents array and project with single agent + // const agents = Array.isArray(project.agents) + // ? project.agents + // : project.agent + // ? [project.agent] + // : []; + + // if (agents.length > 0) { + // logger.debug(`Found ${agents.length} agents in project`); + + // // Prompt for environment variables for all plugins in the project + // try { + // await promptForProjectPlugins(project); + // } catch (error) { + // logger.warn(`Failed to prompt for project environment variables: ${error}`); + // } + + // const startedAgents = []; + // for (const agent of agents) { + // logger.debug(`Debug Agent: ${agent}`); + // try { + // logger.debug(`Starting agent: ${agent.character.name}`); + // const runtime = await startAgent( + // agent.character, + // server, + // agent.init, + // agent.plugins || [] + // ); + // startedAgents.push(runtime); + // // wait .5 seconds + // await new Promise((resolve) => setTimeout(resolve, 500)); + // } catch (agentError) { + // logger.error(`Error starting agent ${agent.character.name}: ${agentError}`); + // } + // } + + // if (startedAgents.length === 0) { + // logger.warn('Failed to start any agents from project, falling back to custom character'); + // await startAgent(defaultCharacter, server); + // } else { + // logger.debug(`Successfully started ${startedAgents.length} agents from project`); + // } + // } else { + // logger.debug('Project found but no agents defined, falling back to custom character'); + // await startAgent(defaultCharacter, server); + // } + // } else if (isPlugin && pluginModule) { + // // Before starting with the plugin, prompt for any environment variables it needs + // if (pluginModule.name) { + // try { + // await promptForEnvVars(pluginModule.name); + // } catch (error) { + // logger.warn(`Failed to prompt for plugin environment variables: ${error}`); + // } + // } + + // // Load the default character with all its default plugins, then add the test plugin + // logger.info( + // `Starting default Eliza character with plugin: ${pluginModule.name || 'unnamed plugin'}` + // ); + + // // Import the default character with all its plugins + // const { character: defaultElizaCharacter } = await import('../characters/eliza'); + + // // Create an array of plugins, including the explicitly loaded one + // // We're using our test plugin plus all the plugins from the default character + // const pluginsToLoad = [pluginModule]; + + // logger.debug( + // `Using default character with plugins: ${defaultElizaCharacter.plugins.join(', ')}` + // ); + // logger.info("Plugin test mode: Using default character's plugins plus the plugin being tested"); + + // // Start the agent with the default character and our test plugin + // // We're in plugin test mode, so we should skip auto-loading embedding models + // await startAgent(defaultElizaCharacter, server, undefined, pluginsToLoad, { + // isPluginTestMode: true, + // }); + // logger.info('Character started with plugin successfully'); + // } else { + // // When not in a project or plugin, load the default character with all plugins + + logger.info('Using default Eliza character with all plugins'); + await startAgent(defaultElizaCharacter, server); + // throw Error("no char") + // } // Display link to the client UI // First try to find it in the CLI package dist/client directory @@ -601,6 +608,7 @@ export const start = new Command() }); // This is the function that registers the command with the CLI + export default function registerCommand(cli: Command) { return cli.addCommand(start); } diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 555230e7fd8..4ba38c4abc7 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -8,18 +8,18 @@ import { dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; import { logger } from '@elizaos/core'; import { Command } from 'commander'; -import { agent } from './commands/agent.js'; -import { create } from './commands/create.js'; -import { dev } from './commands/dev.js'; -import { env } from './commands/env.js'; -import { plugin } from './commands/plugin.js'; -import { project } from './commands/project.js'; -import { publish } from './commands/publish.js'; -import { start } from './commands/start.js'; -import { teeCommand as tee } from './commands/tee.js'; -import { test } from './commands/test.js'; -import { update } from './commands/update.js'; -import { loadEnvironment } from './utils/get-config.js'; +import { agent } from './commands/agent'; +import { create } from './commands/create'; +import { dev } from './commands/dev'; +import { env } from './commands/env'; +import { plugin } from './commands/plugin'; +import { project } from './commands/project'; +import { publish } from './commands/publish'; +import { start } from './commands/start'; +import { teeCommand as tee } from './commands/tee'; +import { test } from './commands/test'; +import { update } from './commands/update'; +import { loadEnvironment } from './utils/get-config'; import { displayBanner } from './displayBanner'; process.on('SIGINT', () => process.exit(0)); process.on('SIGTERM', () => process.exit(0)); diff --git a/packages/cli/src/server/api/agent.ts b/packages/cli/src/server/api/agent.ts index 4814dbf1cee..e1b878b201c 100644 --- a/packages/cli/src/server/api/agent.ts +++ b/packages/cli/src/server/api/agent.ts @@ -276,6 +276,7 @@ export function agentRouter( // Start an existing agent router.post('/:agentId', async (req, res) => { + console.log('start agent req', req); const agentId = validateUuid(req.params.agentId); if (!agentId) { res.status(400).json({ @@ -1761,5 +1762,113 @@ export function agentRouter( } }); + router.post('/groups/:serverId', async (req, res) => { + const serverId = validateUuid(req.params.serverId); + + const { name, worldId, source, metadata, agentIds = [] } = req.body; + + if (!Array.isArray(agentIds) || agentIds.length === 0) { + res.status(400).json({ + success: false, + error: { + code: 'BAD_REQUEST', + message: 'agentIds must be a non-empty array', + }, + }); + } + + let results = []; + let errors = []; + + for (const agentId of agentIds) { + const runtime = agents.get(agentId); + + if (!runtime) { + errors.push({ + agentId, + code: 'NOT_FOUND', + message: 'Agent not found', + }); + continue; + } + + try { + const roomId = createUniqueUuid(runtime, serverId); + const roomName = name || `Chat ${new Date().toLocaleString()}`; + + await runtime.ensureWorldExists({ + id: worldId, + name: source, + agentId: runtime.agentId, + serverId: serverId, + }); + + await runtime.ensureRoomExists({ + id: roomId, + name: roomName, + source, + type: ChannelType.API, + worldId, + serverId, + metadata, + }); + + await runtime.addParticipant(runtime.agentId, roomId); + await runtime.ensureParticipantInRoom(runtime.agentId, roomId); + await runtime.setParticipantUserState(roomId, runtime.agentId, 'FOLLOWED'); + + results.push({ + id: roomId, + name: roomName, + createdAt: Date.now(), + source: 'client', + worldId, + }); + } catch (error) { + logger.error(`[ROOM CREATE] Error creating room for agent ${agentId}:`, error); + errors.push({ + agentId, + code: 'CREATE_ERROR', + message: 'Failed to create room', + details: error.message, + }); + } + } + + if (results.length === 0) { + res.status(500).json({ + success: false, + error: errors.length + ? errors + : [{ code: 'UNKNOWN_ERROR', message: 'No rooms were created' }], + }); + } + + res.status(errors.length ? 207 : 201).json({ + success: errors.length === 0, + data: results, + errors: errors.length ? errors : undefined, + }); + }); + + router.delete('/groups/:serverId', async (req, res) => { + const serverId = validateUuid(req.params.serverId); + try { + await db.deleteRoomsByServerId(serverId); + + res.status(204).send(); + } catch (error) { + logger.error('[GROUP DELETE] Error deleting group:', error); + res.status(500).json({ + success: false, + error: { + code: 'DELETE_ERROR', + message: 'Error deleting group', + details: error.message, + }, + }); + } + }); + return router; } diff --git a/packages/cli/src/server/api/index.ts b/packages/cli/src/server/api/index.ts index 429d40a34cc..74461651aba 100644 --- a/packages/cli/src/server/api/index.ts +++ b/packages/cli/src/server/api/index.ts @@ -11,6 +11,7 @@ import { Server as SocketIOServer } from 'socket.io'; import { SOCKET_MESSAGE_TYPE, EventType, ChannelType } from '@elizaos/core'; import http from 'node:http'; import crypto from 'node:crypto'; +import { worldRouter } from './world'; // Custom levels from @elizaos/core logger const LOG_LEVELS = { @@ -74,181 +75,198 @@ export function setupSocketIO( if (messageData.type === SOCKET_MESSAGE_TYPE.SEND_MESSAGE) { const payload = messageData.payload; - const targetRoomId = payload.roomId; + const socketRoomId = payload.roomId; const worldId = payload.worldId; // Get all agents in this room - const agentsInRoom = roomParticipants.get(targetRoomId) || new Set([targetRoomId as UUID]); + const agentsInRoom = roomParticipants.get(socketRoomId) || new Set([socketRoomId as UUID]); - // Find the primary agent for this room (for simple 1:1 chats) - // In more complex implementations, we'd have a proper room management system - const primaryAgentId = targetRoomId as UUID; - const agentRuntime = agents.get(primaryAgentId); + for (const agentId of agentsInRoom) { + // Find the primary agent for this room (for simple 1:1 chats) + // In more complex implementations, we'd have a proper room management system + const agentRuntime = agents.get(agentId); - const entityId = createUniqueUuid(agentRuntime, payload.senderId); + if (!agentRuntime) { + logger.warn(`Agent runtime not found for ${agentId}`); + continue; + } - if (!agentRuntime) { - logger.warn(`Agent runtime not found for ${primaryAgentId}`); - return; - } + // Ensure the sender and recipient are different agents + if (payload.senderId === agentId) { + logger.debug(`Message sender and recipient are the same agent (${agentId}), ignoring.`); + continue; + } - try { - // Ensure connection between entity and room (just like Discord) - await agentRuntime.ensureConnection({ - entityId: entityId, - roomId: targetRoomId, - userName: payload.senderName || 'User', - name: payload.senderName || 'User', - source: 'client_chat', - channelId: targetRoomId, - serverId: 'client-chat', - type: ChannelType.DM, - worldId: worldId, - }); - - // Create unique message ID - const messageId = crypto.randomUUID() as UUID; - - // Create message object for the agent - const newMessage = { - id: messageId, - entityId: entityId, - agentId: agentRuntime.agentId, - roomId: targetRoomId, - content: { - text: payload.message, - source: payload.source || 'client_chat', - }, - createdAt: Date.now(), - }; - - // No need to save the message here, the bootstrap handler will do it - // Let the messageReceivedHandler in bootstrap.ts handle the memory creation - - // Define callback for agent responses (pattern matching Discord's approach) - const callback = async (content) => { - try { - // Log the content object we received - logger.debug('Callback received content:', { - contentType: typeof content, - contentKeys: content ? Object.keys(content) : 'null', - content: JSON.stringify(content), - }); + if (!payload.message || !payload.message.length) { + logger.warn(`no message found`); + continue; + } + const entityId = createUniqueUuid(agentRuntime, payload.senderId); - // Make sure we have inReplyTo set correctly - if (messageId && !content.inReplyTo) { - content.inReplyTo = messageId; + const uniqueRoomId = createUniqueUuid(agentRuntime, socketRoomId); + const source = payload.source; + try { + // Ensure connection between entity and room (just like Discord) + await agentRuntime.ensureConnection({ + entityId: entityId, + roomId: uniqueRoomId, + userName: payload.senderName || 'User', + name: payload.senderName || 'User', + source: 'client_chat', + channelId: uniqueRoomId, + serverId: 'client-chat', + type: ChannelType.DM, + worldId: worldId, + }); + + // Create unique message ID + const messageId = crypto.randomUUID() as UUID; + + // Create message object for the agent + const newMessage = { + id: messageId, + entityId: entityId, + agentId: agentRuntime.agentId, + roomId: uniqueRoomId, + content: { + text: payload.message, + source: `${source}:${payload.senderName}`, + }, + metadata: { + entityName: payload.senderName, + }, + createdAt: Date.now(), + }; + + // No need to save the message here, the bootstrap handler will do it + // Let the messageReceivedHandler in bootstrap.ts handle the memory creation + + // Define callback for agent responses (pattern matching Discord's approach) + const callback = async (content) => { + try { + // Log the content object we received + logger.debug('Callback received content:', { + contentType: typeof content, + contentKeys: content ? Object.keys(content) : 'null', + content: JSON.stringify(content), + }); + + // Make sure we have inReplyTo set correctly + if (messageId && !content.inReplyTo) { + content.inReplyTo = messageId; + } + + // Prepare broadcast data - more direct and explicit + // Only include required fields to avoid schema validation issues + const broadcastData: Record = { + senderId: agentRuntime.agentId, + senderName: agentRuntime.character.name, + text: content.text || '', + roomId: socketRoomId, + createdAt: Date.now(), + source, + }; + + // Add optional fields only if they exist in the original content + if (content.thought) broadcastData.thought = content.thought; + if (content.actions) broadcastData.actions = content.actions; + + // Log exact broadcast data + logger.debug(`Broadcasting message to room ${socketRoomId}`, { + room: socketRoomId, + clients: io.sockets.adapter.rooms.get(socketRoomId)?.size || 0, + messageText: broadcastData.text?.substring(0, 50), + }); + + logger.debug('Broadcasting data:', JSON.stringify(broadcastData)); + + // Send to specific room first + io.to(socketRoomId).emit('messageBroadcast', broadcastData); + + // Also send to all connected clients as a fallback + logger.debug('Also broadcasting to all clients as fallback'); + io.emit('messageBroadcast', broadcastData); + + // Create memory for the response message (matching Discord's pattern) + const memory = { + id: crypto.randomUUID() as UUID, + entityId: agentRuntime.agentId, + agentId: agentRuntime.agentId, + content: { + ...content, + inReplyTo: messageId, + channelType: ChannelType.DM, + source: `${source}:agent`, + }, + roomId: uniqueRoomId, + createdAt: Date.now(), + }; + + // Log the memory object we're creating + logger.debug('Memory object for response:', { + memoryId: memory.id, + contentKeys: Object.keys(memory.content), + }); + + // Save the memory for the response + await agentRuntime.createMemory(memory, 'messages'); + + // Return content for bootstrap's processing + logger.debug('Returning content directly'); + return [content]; + } catch (error) { + logger.error('Error in socket message callback:', error); + return []; } + }; - // Prepare broadcast data - more direct and explicit - // Only include required fields to avoid schema validation issues - const broadcastData: Record = { - senderId: agentRuntime.agentId, - senderName: agentRuntime.character.name, - text: content.text || '', - roomId: targetRoomId, - createdAt: Date.now(), - source: content.source || 'agent', - }; - - // Add optional fields only if they exist in the original content - if (content.thought) broadcastData.thought = content.thought; - if (content.actions) broadcastData.actions = content.actions; - - // Log exact broadcast data - logger.debug(`Broadcasting message to room ${targetRoomId}`, { - room: targetRoomId, - clients: io.sockets.adapter.rooms.get(targetRoomId)?.size || 0, - messageText: broadcastData.text?.substring(0, 50), - }); + // Log the message and runtime details before calling emitEvent + logger.debug('Emitting MESSAGE_RECEIVED with:', { + messageId: newMessage.id, + entityId: newMessage.entityId, + agentId: newMessage.agentId, + text: newMessage.content.text, + callbackType: typeof callback, + }); - logger.debug('Broadcasting data:', JSON.stringify(broadcastData)); - - // Send to specific room first - io.to(targetRoomId).emit('messageBroadcast', broadcastData); - - // Also send to all connected clients as a fallback - logger.debug('Also broadcasting to all clients as fallback'); - io.emit('messageBroadcast', broadcastData); - - // Create memory for the response message (matching Discord's pattern) - const memory = { - id: crypto.randomUUID() as UUID, - entityId: agentRuntime.agentId, - agentId: agentRuntime.agentId, - content: { - ...content, - inReplyTo: messageId, - channelType: ChannelType.DM, - }, - roomId: targetRoomId, - createdAt: Date.now(), - }; - - // Log the memory object we're creating - logger.debug('Memory object for response:', { - memoryId: memory.id, - contentKeys: Object.keys(memory.content), + // Monkey-patch the emitEvent method to log its arguments + const originalEmitEvent = agentRuntime.emitEvent; + agentRuntime.emitEvent = function (eventType, payload) { + logger.debug('emitEvent called with eventType:', eventType); + logger.debug('emitEvent payload structure:', { + hasRuntime: !!payload.runtime, + hasMessage: !!payload.message, + hasCallback: !!payload.callback, + callbackType: typeof payload.callback, }); + return originalEmitEvent.call(this, eventType, payload); + }; - // Save the memory for the response - await agentRuntime.createMemory(memory, 'messages'); - - // Return content for bootstrap's processing - logger.debug('Returning content directly'); - return [content]; - } catch (error) { - logger.error('Error in socket message callback:', error); - return []; - } - }; - - // Log the message and runtime details before calling emitEvent - logger.debug('Emitting MESSAGE_RECEIVED with:', { - messageId: newMessage.id, - entityId: newMessage.entityId, - agentId: newMessage.agentId, - text: newMessage.content.text, - callbackType: typeof callback, - }); - - // Monkey-patch the emitEvent method to log its arguments - const originalEmitEvent = agentRuntime.emitEvent; - agentRuntime.emitEvent = function (eventType, payload) { - logger.debug('emitEvent called with eventType:', eventType); - logger.debug('emitEvent payload structure:', { - hasRuntime: !!payload.runtime, - hasMessage: !!payload.message, - hasCallback: !!payload.callback, - callbackType: typeof payload.callback, + // Emit message received event to trigger agent's message handler + agentRuntime.emitEvent(EventType.MESSAGE_RECEIVED, { + runtime: agentRuntime, + message: newMessage, + callback, }); - return originalEmitEvent.call(this, eventType, payload); - }; - - // Emit message received event to trigger agent's message handler - agentRuntime.emitEvent(EventType.MESSAGE_RECEIVED, { - runtime: agentRuntime, - message: newMessage, - callback, - }); - } catch (error) { - logger.error('Error processing message:', error); + } catch (error) { + logger.error('Error processing message:', error); + } } } else if (messageData.type === SOCKET_MESSAGE_TYPE.ROOM_JOINING) { const payload = messageData.payload; const roomId = payload.roomId; - const entityId = payload.entityId; + const agentIds = payload.agentIds; + + roomParticipants.set(roomId, new Set()); - // Add entity to room participants if it's an agent - if (agents.has(entityId as UUID)) { - // Initialize Set if not exists - if (!roomParticipants.has(roomId)) { - roomParticipants.set(roomId, new Set()); + agentIds?.forEach((agentId: UUID) => { + if (agents.has(agentId as UUID)) { + // Add agent to room participants + roomParticipants.get(roomId)!.add(agentId as UUID); + logger.debug(`Agent ${agentId} joined room ${roomId}`); } - // Add agent to room participants - roomParticipants.get(roomId)!.add(entityId as UUID); - logger.debug(`Agent ${entityId} joined room ${roomId}`); - } + }); + logger.debug('roomParticipants', roomParticipants); logger.debug(`Client ${socket.id} joining room ${roomId}`); } @@ -510,6 +528,7 @@ export function createApiRouter( // Mount sub-routers router.use('/agents', agentRouter(agents, server)); + router.use('/world', worldRouter(server)); router.use('/tee', teeRouter(agents)); router.get('/stop', (_req, res) => { diff --git a/packages/cli/src/server/api/world.ts b/packages/cli/src/server/api/world.ts new file mode 100644 index 00000000000..7327f5450f4 --- /dev/null +++ b/packages/cli/src/server/api/world.ts @@ -0,0 +1,91 @@ +import { validateUuid } from '@elizaos/core'; +import { logger } from '@elizaos/core'; +import express from 'express'; +import type { AgentServer } from '..'; + +/** + * Creates an express Router for handling world-related routes. + * + * @param server - Optional AgentServer instance. + * @returns An express Router for world routes. + */ +export function worldRouter(server?: AgentServer): express.Router { + const router = express.Router(); + const db = server?.database; + + router.get('/:worldId/rooms', async (req, res) => { + const worldId = validateUuid(req.params.worldId); + try { + const rooms = await db.getRooms(worldId); + + const roomDetails = await Promise.all( + rooms.map(async (roomData) => { + try { + if (!roomData || !roomData.name) return null; + + if (worldId && roomData.worldId !== worldId) { + return null; + } + + const character = await db.getAgent(roomData.agentId); + + return { + id: roomData.id, + name: roomData.name, + source: roomData.source, + worldId: roomData.worldId, + character, + agentId: roomData.agentId, + metadata: roomData.metadata, + serverId: roomData.serverId, + }; + } catch (error) { + logger.error(`[ROOMS GET] Error getting details for room ${roomData.id}:`, error); + return null; + } + }) + ); + + const validRooms = roomDetails.filter((room) => room !== null); + + res.json({ + success: true, + data: validRooms, + }); + } catch (error) { + logger.error(`[ROOMS GET] Error retrieving rooms for agent`, error); + res.status(500).json({ + success: false, + error: { + code: 'FETCH_ERROR', + message: 'Failed to retrieve rooms', + details: error.message, + }, + }); + } + }); + + router.get('/:worldId/memories/:serverId', async (req, res) => { + try { + const { serverId } = req.params; + const memories = await db.getMemoriesByServerId({ serverId, count: 50 }); + + res.json({ + success: true, + data: memories, + }); + } catch (error) { + logger.error(`[ROOMS GET] Error retrieving memories`, error); + res.status(500).json({ + success: false, + error: { + code: 'FETCH_ERROR', + message: 'Failed to retrieve memories', + details: error.message, + }, + }); + } + }); + + return router; +} diff --git a/packages/cli/src/server/index.ts b/packages/cli/src/server/index.ts index 7d365b2b7d5..6f65183847c 100644 --- a/packages/cli/src/server/index.ts +++ b/packages/cli/src/server/index.ts @@ -55,6 +55,7 @@ export class AgentServer { private agents: Map; public server: http.Server; public socketIO: SocketIOServer; + private serverPort: number = 3000; // Add property to store current port public database: any; public startAgent!: (character: Character) => Promise; @@ -113,10 +114,7 @@ export class AgentServer { // wait 250 ms await new Promise((resolve) => setTimeout(resolve, 250)); - // Move this message here to be more accurate - console.log( - `\x1b[32mStartup successful!\nGo to the dashboard at \x1b[1m${AGENT_RUNTIME_URL}\x1b[22m\x1b[0m` - ); + // Success message moved to start method } catch (error) { logger.error('Failed to initialize:', error); throw error; @@ -490,12 +488,19 @@ export class AgentServer { throw new Error(`Invalid port number: ${port}`); } + this.serverPort = port; // Save the port + logger.debug(`Starting server on port ${port}...`); logger.debug(`Current agents count: ${this.agents.size}`); logger.debug(`Environment: ${process.env.NODE_ENV}`); // Use http server instead of app.listen this.server.listen(port, () => { + // Display the dashboard URL with the correct port after the server is actually listening + console.log( + `\x1b[32mStartup successful!\nGo to the dashboard at \x1b[1mhttp://localhost:${port}\x1b[22m\x1b[0m` + ); + logger.success( `REST API bound to 0.0.0.0:${port}. If running locally, access it at http://localhost:${port}.` ); diff --git a/packages/cli/src/utils/cli-prompts.ts b/packages/cli/src/utils/cli-prompts.ts index 98f4dac4812..8c6a153acc3 100644 --- a/packages/cli/src/utils/cli-prompts.ts +++ b/packages/cli/src/utils/cli-prompts.ts @@ -1,5 +1,5 @@ import prompts from 'prompts'; -import { logger } from './logger'; +import { logger } from '@elizaos/core'; export const NAV_BACK = '__back__'; export const NAV_NEXT = '__next__'; diff --git a/packages/cli/src/utils/env-prompt.ts b/packages/cli/src/utils/env-prompt.ts index 2a098e88159..a080e7a8142 100644 --- a/packages/cli/src/utils/env-prompt.ts +++ b/packages/cli/src/utils/env-prompt.ts @@ -114,6 +114,16 @@ const ENV_VAR_CONFIGS: Record = { secret: false, }, ], + postgresql: [ + { + name: 'PostgreSQL URL', + key: 'POSTGRES_URL', + required: false, + description: 'URL for connecting to your PostgreSQL database.', + url: 'https://neon.tech/docs/connect/connect-from-any-app', + secret: false, + }, + ], }; /** @@ -488,6 +498,19 @@ export function validatePluginConfig(pluginName: string): { message: 'Anthropic API is properly configured.', }; + case 'postgresql': + if (!envVars.POSTGRES_URL || envVars.POSTGRES_URL.trim() === '') { + return { + valid: true, // Not required by default + message: 'PostgreSQL URL is not configured. Using default PGLite database.', + }; + } + + return { + valid: true, + message: 'PostgreSQL connection is configured.', + }; + default: return { valid: true, diff --git a/packages/cli/src/utils/get-config.ts b/packages/cli/src/utils/get-config.ts index d3141df6204..9ce41d2704d 100644 --- a/packages/cli/src/utils/get-config.ts +++ b/packages/cli/src/utils/get-config.ts @@ -3,6 +3,8 @@ import os from 'node:os'; import path from 'node:path'; import dotenv from 'dotenv'; import { z } from 'zod'; +import prompts from 'prompts'; +import { logger } from '@elizaos/core'; // Database config schemas const postgresConfigSchema = z.object({ @@ -19,6 +21,238 @@ const pgliteConfigSchema = z.object({ }), }); +/** + * Validates a Postgres URL format + * @param url The URL to validate + * @returns True if the URL appears valid + */ +export function isValidPostgresUrl(url: string): boolean { + if (!url) return false; + + // Basic pattern: postgresql://user:password@host:port/dbname + const basicPattern = /^postgresql:\/\/[^:]+:[^@]+@[^:]+:\d+\/\w+$/; + + // More permissive pattern (allows missing password, different formats) + const permissivePattern = /^postgresql:\/\/.*@.*:\d+\/.*$/; + + // Cloud pattern: allows for URLs with query parameters like sslmode=require + const cloudPattern = /^postgresql:\/\/[^:]+:[^@]+@[^\/]+\/[^?]+(\?.*)?$/; + + return basicPattern.test(url) || cloudPattern.test(url) || permissivePattern.test(url); +} + +/** + * Gets the standard Eliza directories + * @returns Object containing standard directory paths + */ +export function getElizaDirectories() { + const homeDir = os.homedir(); + const elizaDir = path.join(homeDir, '.eliza'); + const elizaDbDir = path.join(elizaDir, 'db'); + const envFilePath = path.join(elizaDir, '.env'); + + return { + homeDir, + elizaDir, + elizaDbDir, + envFilePath, + }; +} + +/** + * Ensures the .eliza directory exists + * @returns The eliza directories object + */ +export async function ensureElizaDir() { + const dirs = getElizaDirectories(); + + if (!existsSync(dirs.elizaDir)) { + await fs.mkdir(dirs.elizaDir, { recursive: true }); + logger.info(`Created directory: ${dirs.elizaDir}`); + } + + return dirs; +} + +/** + * Ensures the .env file exists + * @param envFilePath Path to the .env file + */ +export async function ensureEnvFile(envFilePath: string) { + if (!existsSync(envFilePath)) { + await fs.writeFile(envFilePath, '', { encoding: 'utf8' }); + logger.debug(`Created empty .env file at ${envFilePath}`); + } +} + +/** + * Sets up and configures PGLite database + * @param elizaDbDir The directory for PGLite database + * @param envFilePath Path to the .env file + */ +export async function setupPgLite(elizaDbDir: string, envFilePath: string): Promise { + try { + // Ensure the PGLite database directory exists + if (!existsSync(elizaDbDir)) { + await fs.mkdir(elizaDbDir, { recursive: true }); + logger.info(`Created PGLite database directory: ${elizaDbDir}`); + } + + // Ensure .env file exists + await ensureEnvFile(envFilePath); + + // Store PGLITE_DATA_DIR in the environment file + await fs.writeFile(envFilePath, `PGLITE_DATA_DIR=${elizaDbDir}\n`, { flag: 'a' }); + + // Also set in process.env for the current session + process.env.PGLITE_DATA_DIR = elizaDbDir; + + logger.success('PGLite configuration saved'); + } catch (error) { + logger.error('Error setting up PGLite directory:', error); + throw error; + } +} + +/** + * Stores Postgres URL in the .env file + * @param url The Postgres URL to store + * @param envFilePath Path to the .env file + */ +export async function storePostgresUrl(url: string, envFilePath: string): Promise { + if (!url) return; + + try { + // Ensure .env file exists + await ensureEnvFile(envFilePath); + + // Store the URL in the .env file + await fs.writeFile(envFilePath, `POSTGRES_URL=${url}\n`, { flag: 'a' }); + + // Also set in process.env for the current session + process.env.POSTGRES_URL = url; + + logger.success('Postgres URL saved to configuration'); + } catch (error) { + logger.warn('Error saving database configuration:', error); + } +} + +/** + * Prompts the user for a Postgres URL, validates it, and stores it + * @returns The configured Postgres URL or null if user skips + */ +/** + * Prompts the user for a Postgres URL, validates it, and stores it + * @returns The configured Postgres URL or null if user cancels + */ +export async function promptAndStorePostgresUrl(envFilePath: string): Promise { + const response = await prompts({ + type: 'text', + name: 'postgresUrl', + message: 'Enter your Postgres URL:', + validate: (value) => { + if (value.trim() === '') return 'Postgres URL cannot be empty'; + + const isValid = isValidPostgresUrl(value); + if (!isValid) { + return `Invalid URL format. Expected: postgresql://user:password@host:port/dbname.`; + } + return true; + }, + }); + + // Handle user cancellation (Ctrl+C) + if (!response.postgresUrl) { + return null; + } + + // Store the URL in the .env file + await storePostgresUrl(response.postgresUrl, envFilePath); + + return response.postgresUrl; +} + +/** + * Configures the database to use, either PGLite or PostgreSQL + * @param reconfigure If true, force reconfiguration even if already configured + * @returns The postgres URL if using Postgres, otherwise null + */ +export async function configureDatabaseSettings(reconfigure = false): Promise { + // Set up directories and env file + const { elizaDbDir, envFilePath } = await ensureElizaDir(); + await ensureEnvFile(envFilePath); + + // Check if we already have database configuration in env + let postgresUrl = process.env.POSTGRES_URL; + const pgliteDataDir = process.env.PGLITE_DATA_DIR; + + // If we already have a postgres URL configured and not reconfiguring, use that + if (postgresUrl && !reconfigure) { + logger.debug('Using existing PostgreSQL configuration'); + return postgresUrl; + } + + // If we already have PGLITE_DATA_DIR set in env and not reconfiguring, use PGLite + if (pgliteDataDir && !reconfigure) { + logger.debug(`Using existing PGLite configuration: ${pgliteDataDir}`); + + // Ensure the directory exists + if (!existsSync(pgliteDataDir)) { + await fs.mkdir(pgliteDataDir, { recursive: true }); + logger.info(`Created PGLite database directory: ${pgliteDataDir}`); + } + + return null; + } + + try { + // Prompt for database selection + const { database } = await prompts({ + type: 'select', + name: 'database', + message: 'Select your database:', + choices: [ + { title: 'pglite (embedded database)', value: 'pglite' }, + { title: 'postgres (external database)', value: 'postgres' }, + ], + initial: 0, + }); + + if (!database || database === 'pglite') { + // If selection canceled or pglite selected + const dbChoice = !database ? 'Selection canceled, defaulting to' : 'Selected'; + logger.info(`${dbChoice} pglite database`); + + await setupPgLite(elizaDbDir, envFilePath); + return null; + } + + // User selected postgres + const result = await promptAndStorePostgresUrl(envFilePath); + if (!result) { + // If no valid Postgres URL provided, default to PGLite + logger.warn('No valid Postgres URL provided, defaulting to pglite database'); + await setupPgLite(elizaDbDir, envFilePath); + return null; + } + + return result; + } catch (error) { + logger.error('Error during database configuration:', error); + logger.info('Defaulting to pglite database'); + + try { + await setupPgLite(elizaDbDir, envFilePath); + } catch (setupError) { + logger.error('Critical error setting up database:', setupError); + throw new Error('Failed to configure database'); + } + } + + return null; // Default to pglite +} + // Main config schema /** * Schema definition for the raw configuration object. diff --git a/packages/client/package.json b/packages/client/package.json index 46a3ab6cedb..94d5898bbe9 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -20,6 +20,7 @@ "@radix-ui/react-avatar": "^1.1.3", "@radix-ui/react-collapsible": "^1.1.3", "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", "@radix-ui/react-label": "^2.1.2", "@radix-ui/react-scroll-area": "^1.2.3", "@radix-ui/react-select": "^2.1.6", @@ -41,6 +42,7 @@ "react": "^19.0.0", "react-aiwriter": "^1.0.0", "react-dom": "^19.0.0", + "react-resizable-panels": "^2.1.7", "react-router": "^7.3.0", "react-router-dom": "^7.3.0", "semver": "^7.7.1", diff --git a/packages/client/src/App.tsx b/packages/client/src/App.tsx index 9704ca9900e..2fd5834e65f 100644 --- a/packages/client/src/App.tsx +++ b/packages/client/src/App.tsx @@ -12,6 +12,7 @@ import { STALE_TIMES } from './hooks/use-query-hooks'; import useVersion from './hooks/use-version'; import { apiClient } from './lib/api'; import Chat from './routes/chat'; +import Room from './routes/room'; import AgentCreatorRoute from './routes/createAgent'; import Home from './routes/home'; import Settings from './routes/settings'; @@ -86,6 +87,7 @@ function App() { } /> } /> } /> + } /> diff --git a/packages/client/src/components/action-viewer.tsx b/packages/client/src/components/action-viewer.tsx index 15273cdf663..3350a8c917e 100644 --- a/packages/client/src/components/action-viewer.tsx +++ b/packages/client/src/components/action-viewer.tsx @@ -1,10 +1,121 @@ -import type { UUID, ModelType } from '@elizaos/core'; +import type { UUID } from '@elizaos/core'; import { Bot, Brain, ImagePlusIcon, Trash2 } from 'lucide-react'; import { useAgentActions, useDeleteLog } from '../hooks/use-query-hooks'; import { Badge } from './ui/badge'; import { Button } from './ui/button'; +import { ScrollArea } from './ui/scroll-area'; -export function AgentActionViewer({ agentId, roomId }: { agentId: UUID; roomId?: UUID }) { +type AgentAction = { + id?: string; + type?: string; + createdAt?: number; + body?: { + modelType?: string; + modelKey?: string; + params?: any; + response?: any; + }; +}; + +type ActionCardProps = { + action: AgentAction; + onDelete?: (logId: string) => void; +}; + +// Internal ActionCard component +function ActionCard({ action, onDelete }: ActionCardProps) { + const formatDate = (timestamp: number) => { + const date = new Date(timestamp); + return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`; + }; + + const getModelIcon = (modelType = '') => { + if (modelType.includes('TEXT_EMBEDDING')) return ; + if (modelType.includes('LLM')) return ; + if (modelType.includes('IMAGE')) return ; + return ; + }; + + const renderActionContent = () => { + const { body } = action; + + return ( + <> + {body?.modelKey && ( +
+ Model: + {body.modelKey} +
+ )} + + {body?.params && ( +
+ Params: + {typeof body.params === 'object' ? JSON.stringify(body.params, null, 2) : body.params} +
+ )} + + {body?.response && ( +
+ {body.response === '[array]' ? ( + 'Response contains array data' + ) : ( + <> + Response: + {typeof body.response === 'object' + ? JSON.stringify(body.response, null, 2) + : body.response} + + )} +
+ )} + + ); + }; + + const modelType = action.body?.modelType || ''; + const actionType = action.type || 'Action'; + + return ( +
+ {action.id && onDelete && ( + + )} + +
+ + {getModelIcon(modelType)} {actionType} + + + {formatDate(action.createdAt)} + +
+ +
{renderActionContent()}
+
+ ); +} + +type AgentActionViewerProps = { + agentId: UUID; + roomId?: UUID; +}; + +export function AgentActionViewer({ agentId, roomId }: AgentActionViewerProps) { const { data: actions = [], isLoading, error } = useAgentActions(agentId, roomId); const { mutate: deleteLog } = useDeleteLog(); @@ -20,111 +131,26 @@ export function AgentActionViewer({ agentId, roomId }: { agentId: UUID; roomId?: ); } - const formatDate = (timestamp: number) => { - const date = new Date(timestamp); - return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`; - }; - - const getModelIcon = (modelType: string) => { - if (modelType?.includes('TEXT_EMBEDDING')) return ; - if (modelType?.includes('LLM')) return ; - if (modelType?.includes('IMAGE')) return ; - return ; - }; - const handleDelete = (logId: string) => { - if (logId && window.confirm('Are you sure you want to delete this log entry?')) { + if (window.confirm('Are you sure you want to delete this log entry?')) { deleteLog({ agentId, logId }); } }; return ( -
+

Agent Actions

-
+ {actions.length === 0 ? (
No actions recorded yet
) : ( -
- {actions.map((action, index) => { - const modelType = action.body?.modelType || ''; - const actionType = action.type || 'Action'; - - return ( -
- {action.id && ( - - )} - -
- - {getModelIcon(modelType)} {actionType} - - - {formatDate(action.createdAt)} - -
- -
- {action.body?.modelKey && ( -
- Model: - {action.body.modelKey} -
- )} - - {action.body?.params && ( -
- Params: - {typeof action.body.params === 'object' - ? JSON.stringify(action.body.params, null, 2) - : action.body.params} -
- )} - - {action.body?.response && ( -
- {action.body.response === '[array]' ? ( - 'Response contains array data' - ) : ( - <> - Response: - {typeof action.body.response === 'object' - ? JSON.stringify(action.body.response, null, 2) - : action.body.response} - - )} -
- )} -
-
- ); - })} -
+ actions.map((action, index) => ( + + )) )} -
+
); } diff --git a/packages/client/src/components/agent-avatar-stack.tsx b/packages/client/src/components/agent-avatar-stack.tsx new file mode 100644 index 00000000000..11f1e114dff --- /dev/null +++ b/packages/client/src/components/agent-avatar-stack.tsx @@ -0,0 +1,75 @@ +import { UUID } from '@elizaos/core'; +import { Avatar, AvatarImage } from './ui/avatar'; +import { formatAgentName } from '@/lib/utils'; + +interface AgentAvatarStackProps { + agentIds: UUID[]; + agentNames: string[]; + agentAvatars: Record; + size?: 'sm' | 'md' | 'lg'; + maxStack?: number; +} + +export default function AgentAvatarStack({ + agentIds, + agentNames, + agentAvatars, + size = 'md', + maxStack = 2, +}: AgentAvatarStackProps) { + const displayAgents = agentIds.slice(0, maxStack); + const isMultiple = displayAgents.length > 1; + + const baseSize = size === 'sm' ? 24 : size === 'lg' ? 40 : 32; + const avatarSizeClass = isMultiple + ? size === 'sm' + ? 'size-5' + : size === 'lg' + ? 'size-9' + : 'size-7' + : size === 'sm' + ? 'size-6' + : size === 'lg' + ? 'size-10' + : 'size-8'; + + const avatarOffset = Math.floor(baseSize * (0.6 / maxStack)); + + const getAvatarContent = (agentId: UUID, index: number) => { + const avatarSrc = agentAvatars[agentId] || '/elizaos-icon.png'; + return agentAvatars[agentId] ? ( + + ) : ( +
+ {formatAgentName(agentNames[index])} +
+ ); + }; + + return ( +
+ {displayAgents.length === 1 ? ( + + {getAvatarContent(displayAgents[0], 0)} + + ) : ( + displayAgents.map((agentId, index) => ( + + {getAvatarContent(agentId, index)} + + )) + )} +
+ ); +} diff --git a/packages/client/src/components/agent-sidebar.tsx b/packages/client/src/components/agent-sidebar.tsx new file mode 100644 index 00000000000..dc8a0d33a27 --- /dev/null +++ b/packages/client/src/components/agent-sidebar.tsx @@ -0,0 +1,61 @@ +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { Activity, Book, Database, Terminal } from 'lucide-react'; +import { AgentActionViewer } from './action-viewer'; +import { LogViewer } from './log-viewer'; +import { AgentMemoryViewer } from './memory-viewer'; +import { KnowledgeManager } from './knowledge-manager'; +import type { UUID } from '@elizaos/core'; +import { useState } from 'react'; + +type AgentSidebarProps = { + agentId: UUID; + agentName: string; +}; + +export function AgentSidebar({ agentId, agentName }: AgentSidebarProps) { + const [detailsTab, setDetailsTab] = useState<'actions' | 'logs' | 'memories' | 'knowledge'>( + 'actions' + ); + return ( + setDetailsTab(v as 'actions' | 'logs' | 'memories' | 'knowledge')} + className="flex flex-col h-full" + > +
+ + + + Actions + + + + Memories + + + + Knowledge + + + + Logs + + +
+ + + + + + + + + + + + + +
+ ); +} diff --git a/packages/client/src/components/app-sidebar.tsx b/packages/client/src/components/app-sidebar.tsx index a017dcc7762..18248389d60 100644 --- a/packages/client/src/components/app-sidebar.tsx +++ b/packages/client/src/components/app-sidebar.tsx @@ -4,213 +4,325 @@ import { SidebarFooter, SidebarGroup, SidebarGroupContent, - SidebarGroupLabel, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, } from '@/components/ui/sidebar'; -import { useAgents } from '@/hooks/use-query-hooks'; +import { useAgents, useRooms } from '@/hooks/use-query-hooks'; import info from '@/lib/info.json'; import { formatAgentName } from '@/lib/utils'; -import { type Agent, AgentStatus } from '@elizaos/core'; -import { Book, Cog, TerminalIcon } from 'lucide-react'; +import { AgentStatus, type UUID } from '@elizaos/core'; +import type { Agent } from '@elizaos/core'; +import { Book, Cog, Plus, TerminalIcon } from 'lucide-react'; +import { useEffect, useState } from 'react'; import { NavLink, useLocation } from 'react-router'; +import AgentAvatarStack from './agent-avatar-stack'; import ConnectionStatus from './connection-status'; +import GroupPanel from './group-panel'; +import { Button } from './ui/button'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from './ui/dropdown-menu'; export function AppSidebar() { + const [onlineAgents, setOnlineAgents] = useState([]); + const [offlineAgents, setOfflineAgents] = useState([]); + const { data: roomsData, isLoading: roomsLoading } = useRooms(); + const { data: { data: agentsData } = {}, isLoading: agentsLoading } = useAgents(); const location = useLocation(); - // Add more defensive coding to handle any possible null/undefined responses - const agentsResult = useAgents(); - const { data, isPending: isAgentsPending } = agentsResult || { data: undefined, isPending: true }; + // Extract agents from the response + const agents = agentsData?.agents || []; + + const isRoomPage = location.pathname.startsWith('/room/'); + const match = location.pathname.match(/^\/room\/([^/]+)$/); + const roomId = match ? match[1] : null; + + // Create a map of agent avatars for easy lookup + const agentAvatars: Record = {}; + for (const agent of agents) { + if (agent.id && agent.settings?.avatar) { + agentAvatars[agent.id] = agent.settings.avatar; + } + } + + const [isGroupPanelOpen, setIsGroupPanelOpen] = useState(false); + + useEffect(() => { + // Split into online and offline agents + let onlineAgents = agents.filter( + (agent: Partial) => agent.status === AgentStatus.ACTIVE + ); - // Create a safe data object that can't be null - const safeData = data || {}; - const safeDataData = (safeData as any).data || {}; - const agents = safeDataData.agents || []; + let offlineAgents = agents.filter( + (agent: Partial) => agent.status === AgentStatus.INACTIVE + ); + if (isRoomPage) { + if (roomId) { + onlineAgents = [...onlineAgents].filter((agent) => + roomsData?.get(roomId)?.some((room) => room.agentId === agent.id) + ); + offlineAgents = [...offlineAgents].filter((agent) => + roomsData?.get(roomId)?.some((room) => room.agentId === agent.id) + ); + } + } + + setOnlineAgents(onlineAgents); + setOfflineAgents(offlineAgents); + }, [isRoomPage, agentsData, roomId]); return ( - - - - - - -
- elizaos-logo - - v{info?.version} - -
-
-
-
-
-
- - - - - {isAgentsPending ? ( -
- {Array.from({ length: 5 }).map((_, _index) => ( - - - - ))} -
- ) : ( -
- {(() => { - // Sort agents: enabled first, then disabled - const sortedAgents = [...agents].sort((a, b) => { - // Sort by status (active agents first) - if (a.status === AgentStatus.ACTIVE && b.status !== AgentStatus.ACTIVE) - return -1; - if (a.status !== AgentStatus.ACTIVE && b.status === AgentStatus.ACTIVE) - return 1; - // If both have the same status, sort alphabetically by name - return a.name.localeCompare(b.name); - }); - - // Split into enabled and disabled groups - const activeAgents = sortedAgents.filter( - (agent: Partial) => - agent.status === AgentStatus.ACTIVE - ); - const inactiveAgents = sortedAgents.filter( - (agent: Partial) => - agent.status === AgentStatus.INACTIVE - ); - - return ( - <> - {/* Render active section */} - {activeAgents.length > 0 && ( -
-
- - Online - -
-
- )} - - {/* Render enabled agents */} - {activeAgents.map((agent) => ( - - - -
-
-
- {agent && ( -
- {agent.settings?.avatar ? ( - Agent Avatar - ) : ( - formatAgentName(agent.name) - )} -
-
+ <> + + + + + + +
+ elizaos-logo + + v{info?.version} + +
+
+
+
+
+
+ + {/* Create Button with Dropdown */} +
+ + + + + + + + Create Agent + + + { + setIsGroupPanelOpen(true); + }} + className="flex items-center cursor-pointer" + > + Create Room + + + +
+ + {isGroupPanelOpen && ( + { + setIsGroupPanelOpen(false); + }} + /> + )} + + {/* Agents Section */} + + + + {agentsLoading ? ( +
+ {Array.from({ length: 5 }).map((_, _index) => ( + + + + ))} +
+ ) : ( +
+ {/* Online Agents */} + {onlineAgents.length > 0 && ( +
+
+ Online +
+
+ )} + + {/* Render enabled agents */} + {onlineAgents.map((agent) => ( + + + +
+
+
+ {agent && ( +
+ {agent.settings?.avatar ? ( + Agent Avatar + ) : ( + formatAgentName(agent.name) )} +
-
- {agent.name} + )}
- - - - ))} - - {/* Render inactive section */} - {inactiveAgents.length > 0 && ( -
-
- - Offline - +
+ {agent.name}
-
- )} - - {/* Render disabled agents */} - {inactiveAgents.map((agent) => ( - -
-
-
-
- {agent && ( -
- {agent.settings?.avatar ? ( - Agent Avatar - ) : ( - formatAgentName(agent.name) - )} -
-
+ + + + ))} + + {/* Offline Agents */} + {offlineAgents.length > 0 && ( +
+
+ Offline +
+
+ )} + + {/* Render disabled agents */} + {offlineAgents.map((agent) => ( + +
+
+
+
+ {agent && ( +
+ {agent.settings?.avatar ? ( + Agent Avatar + ) : ( + formatAgentName(agent.name) )} +
-
- {agent.name} + )}
+ {agent.name} +
+
+
+ ))} +
+ )} + + + + + {/* Groups Section */} + + + + {roomsLoading ? ( +
+ {Array.from({ length: 5 }).map((_, _index) => ( + + + + ))} +
+ ) : ( +
+
+
+ Groups +
+
+ {roomsData && + Array.from(roomsData.entries()).map(([roomId, roomArray]) => { + // Get room name + const roomName = roomArray.length > 0 ? roomArray[0]?.name : null; + + // Get agent IDs for this room + const roomAgentIds = roomArray + .map((room) => room.agentId) + .filter(Boolean) as UUID[]; + const roomAgentNames = roomArray + .map((room) => room.character.name) + .filter(Boolean) as string[]; + + return ( + + + +
+ +
+
{roomName}
+
+ {`${roomAgentIds.length} ${roomAgentIds.length === 1 ? 'Member' : 'Members'}`} +
+
+
+
+
- ))} - - ); - })()} -
- )} -
-
-
- - - - - - - - Documentation - - - - - - - - Logs + ); + })} +
+ )} + + + + + + + + + + + Documentation + + + + + + + + Logs + + + + + + + Settings - - - - - - Settings - - - - - - + + + + + + ); } diff --git a/packages/client/src/components/avatar-panel.tsx b/packages/client/src/components/avatar-panel.tsx index 73f7b2e4e4f..178f6d140e1 100644 --- a/packages/client/src/components/avatar-panel.tsx +++ b/packages/client/src/components/avatar-panel.tsx @@ -2,6 +2,7 @@ import { Button } from '@/components/ui/button'; import type { Agent } from '@elizaos/core'; import { Image as ImageIcon, Upload, X } from 'lucide-react'; import { useEffect, useRef, useState } from 'react'; +import { compressImage } from '@/lib/utils'; interface AvatarPanelProps { characterValue: Agent; @@ -12,43 +13,15 @@ export default function AvatarPanel({ characterValue, setCharacterValue }: Avata const [avatar, setAvatar] = useState(characterValue?.settings?.avatar || null); const fileInputRef = useRef(null); - const handleFileUpload = (event: React.ChangeEvent) => { + const handleFileUpload = async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (file) { - const reader = new FileReader(); - reader.onload = (e) => { - if (e.target?.result) { - const img = new Image(); - img.src = e.target.result as string; - img.onload = () => { - const canvas = document.createElement('canvas'); - const maxSize = 300; // Resize to max 300px width/height - let width = img.width; - let height = img.height; - - if (width > height) { - if (width > maxSize) { - height *= maxSize / width; - width = maxSize; - } - } else { - if (height > maxSize) { - width *= maxSize / height; - height = maxSize; - } - } - - canvas.width = width; - canvas.height = height; - const ctx = canvas.getContext('2d'); - ctx?.drawImage(img, 0, 0, width, height); - const resizedBase64 = canvas.toDataURL('image/jpeg', 0.8); // Reduce quality to 80% - - setAvatar(resizedBase64); - }; - } - }; - reader.readAsDataURL(file); + try { + const compressedImage = await compressImage(file); + setAvatar(compressedImage); + } catch (error) { + console.error('Error compressing image:', error); + } } }; diff --git a/packages/client/src/components/character-form.tsx b/packages/client/src/components/character-form.tsx index a98139ba8a9..8c69ff8fa17 100644 --- a/packages/client/src/components/character-form.tsx +++ b/packages/client/src/components/character-form.tsx @@ -5,7 +5,9 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Textarea } from '@/components/ui/textarea'; +import { AVATAR_IMAGE_MAX_SIZE } from '@/constants'; import { useToast } from '@/hooks/use-toast'; +import { compressImage } from '@/lib/utils'; import type { Agent } from '@elizaos/core'; import type React from 'react'; import { type FormEvent, type ReactNode, useState } from 'react'; @@ -200,12 +202,36 @@ export default function CharacterForm({ }); }; + const ensureAvatarSize = async (char: Agent): Promise => { + if (char.settings?.avatar) { + const img = new Image(); + img.src = char.settings.avatar; + await new Promise((resolve) => (img.onload = resolve)); + + if (img.width > AVATAR_IMAGE_MAX_SIZE || img.height > AVATAR_IMAGE_MAX_SIZE) { + const response = await fetch(char.settings.avatar); + const blob = await response.blob(); + const file = new File([blob], 'avatar.jpg', { type: blob.type }); + const compressedImage = await compressImage(file); + return { + ...char, + settings: { + ...char.settings, + avatar: compressedImage, + }, + }; + } + } + return char; + }; + const handleSubmit = async (e: FormEvent) => { e.preventDefault(); setIsSubmitting(true); try { - await onSubmit(characterValue); + const updatedCharacter = await ensureAvatarSize(characterValue); + await onSubmit(updatedCharacter); } catch (error) { toast({ title: 'Error', diff --git a/packages/client/src/components/chat.tsx b/packages/client/src/components/chat.tsx index cb591f32cb6..14684a94a3e 100644 --- a/packages/client/src/components/chat.tsx +++ b/packages/client/src/components/chat.tsx @@ -7,42 +7,28 @@ import { import { ChatInput } from '@/components/ui/chat/chat-input'; import { ChatMessageList } from '@/components/ui/chat/chat-message-list'; import { USER_NAME } from '@/constants'; -import { useAgent, useMessages } from '@/hooks/use-query-hooks'; -import { cn, getEntityId, moment } from '@/lib/utils'; +import { useMessages } from '@/hooks/use-query-hooks'; import SocketIOManager from '@/lib/socketio-manager'; +import { cn, getEntityId, moment, randomUUID } from '@/lib/utils'; import { WorldManager } from '@/lib/world-manager'; -import { randomUUID } from '@/lib/utils'; import type { IAttachment } from '@/types'; -import type { Content, UUID } from '@elizaos/core'; +import type { Agent, Content, UUID } from '@elizaos/core'; import { AgentStatus } from '@elizaos/core'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@radix-ui/react-collapsible'; + import { useQueryClient } from '@tanstack/react-query'; -import { - Activity, - ChevronRight, - Database, - PanelRight, - Paperclip, - Send, - Terminal, - X, -} from 'lucide-react'; -import { useEffect, useRef, useState, useCallback } from 'react'; +import { ChevronRight, PanelRight, Paperclip, Send, X } from 'lucide-react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import AIWriter from 'react-aiwriter'; -import { AgentActionViewer } from './action-viewer'; import { AudioRecorder } from './audio-recorder'; import CopyButton from './copy-button'; -import { LogViewer } from './log-viewer'; -import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar'; +import { Avatar, AvatarImage } from './ui/avatar'; import { Badge } from './ui/badge'; import ChatTtsButton from './ui/chat/chat-tts-button'; import { useAutoScroll } from './ui/chat/hooks/useAutoScroll'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'; import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip'; -import { AgentMemoryViewer } from './memory-viewer'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@radix-ui/react-collapsible'; -import React from 'react'; -const SOURCE_NAME = 'client_chat'; +import { CHAT_SOURCE } from '@/constants'; type ExtraContentFields = { name: string; @@ -63,16 +49,6 @@ function MessageContent({ agentId: UUID; isLastMessage: boolean; }) { - // Only log message details in development mode - if (import.meta.env.DEV) { - console.log(`[Chat] Rendering message from ${message.name}:`, { - isUser: message.name === USER_NAME, - text: message.text?.substring(0, 20) + '...', - senderId: message.senderId, - source: message.source, - }); - } - return (
- - {!message.text && message.thought && ( - <> - {message.name === USER_NAME ? ( - message.thought - ) : isLastMessage && message.name !== USER_NAME ? ( - - {message.thought} - - ) : ( + {!message.text && + message.thought && + (message.name === USER_NAME ? ( + message.thought + ) : isLastMessage && message.name !== USER_NAME ? ( + {message.thought} - )} - - )} + + ) : ( + {message.thought} + ))} {message.attachments?.map((attachment: IAttachment) => (
@@ -166,18 +139,27 @@ function MessageContent({ ); } -export default function Page({ agentId }: { agentId: UUID }) { +export default function Page({ + agentId, + worldId, + agentData, + showDetails, + toggleDetails, +}: { + agentId: UUID; + worldId: UUID; + agentData: Agent; + showDetails: boolean; + toggleDetails: () => void; +}) { const [selectedFile, setSelectedFile] = useState(null); const [input, setInput] = useState(''); - const [showDetails, setShowDetails] = useState(false); - const [detailsTab, setDetailsTab] = useState<'actions' | 'logs' | 'memories'>('actions'); + const inputRef = useRef(null); const fileInputRef = useRef(null); const formRef = useRef(null); const queryClient = useQueryClient(); - const worldId = WorldManager.getWorldId(); - const agentData = useAgent(agentId)?.data?.data; const entityId = getEntityId(); const roomId = WorldManager.generateRoomId(agentId); @@ -187,7 +169,7 @@ export default function Page({ agentId }: { agentId: UUID }) { useEffect(() => { // Initialize Socket.io connection once with our entity ID - socketIOManager.initialize(entityId); + socketIOManager.initialize(entityId, [agentId]); // Join the room for this agent socketIOManager.joinRoom(roomId); @@ -195,7 +177,7 @@ export default function Page({ agentId }: { agentId: UUID }) { console.log(`[Chat] Joined room ${roomId} with entityId ${entityId}`); const handleMessageBroadcasting = (data: ContentWithUser) => { - console.log(`[Chat] Received message broadcast:`, data); + console.log('[Chat] Received message broadcast:', data); // Skip messages that don't have required content if (!data) { @@ -229,7 +211,7 @@ export default function Page({ agentId }: { agentId: UUID }) { queryClient.setQueryData( ['messages', agentId, roomId, worldId], (old: ContentWithUser[] = []) => { - console.log(`[Chat] Current messages:`, old?.length || 0); + console.log('[Chat] Current messages:', old?.length || 0); // Check if this message is already in the list (avoid duplicates) const isDuplicate = old.some( @@ -253,7 +235,7 @@ export default function Page({ agentId }: { agentId: UUID }) { }; // Add listener for message broadcasts - console.log(`[Chat] Adding messageBroadcast listener`); + console.log('[Chat] Adding messageBroadcast listener'); socketIOManager.on('messageBroadcast', handleMessageBroadcasting); return () => { @@ -262,7 +244,7 @@ export default function Page({ agentId }: { agentId: UUID }) { socketIOManager.leaveRoom(roomId); socketIOManager.off('messageBroadcast', handleMessageBroadcasting); }; - }, [roomId, agentId, entityId]); + }, [roomId, agentId, entityId, queryClient, socketIOManager]); // Use a stable ID for refs to avoid excessive updates const scrollRefId = useRef(`scroll-${Math.random().toString(36).substring(2, 9)}`).current; @@ -315,7 +297,7 @@ export default function Page({ agentId }: { agentId: UUID }) { senderId: entityId, senderName: USER_NAME, roomId: roomId, - source: SOURCE_NAME, + source: CHAT_SOURCE, id: randomUUID(), // Add a unique ID for React keys and duplicate detection }; @@ -346,7 +328,7 @@ export default function Page({ agentId }: { agentId: UUID }) { // via the useEffect hook // Send the message to the server/agent - socketIOManager.sendMessage(input, roomId, SOURCE_NAME); + socketIOManager.sendMessage(input, roomId, CHAT_SOURCE); setSelectedFile(null); setInput(''); @@ -366,12 +348,10 @@ export default function Page({ agentId }: { agentId: UUID }) { } }; - const toggleDetails = () => { - setShowDetails(!showDetails); - }; - return ( -
+
{/* Agent Header */}
@@ -423,12 +403,7 @@ export default function Page({ agentId }: { agentId: UUID }) {
{/* Main Chat Area */} -
+
{/* Chat Messages */} {messages.map((message: ContentWithUser, index: number) => { - // Ensure user messages are correctly identified by either name or source - const isUser = - message.name === USER_NAME || - message.source === SOURCE_NAME || - message.senderId === entityId; - - // Add debugging to see why user message might be misattributed - if (!isUser && (message.source === SOURCE_NAME || message.senderId === entityId)) { - console.warn('[Chat] Message attribution issue detected:', { - message, - name: message.name, - expectedName: USER_NAME, - source: message.source, - expectedSource: SOURCE_NAME, - senderId: message.senderId, - entityId, - }); - } + const isUser = message.name === USER_NAME; return (
- - {/* Details Column */} - {showDetails && ( -
- setDetailsTab(v as 'actions' | 'logs' | 'memories')} - className="flex flex-col h-full" - > -
- - - - Agent Actions - - - - Logs - - - - Memories - - -
- - - - - - - - - - -
-
- )}
); diff --git a/packages/client/src/components/combobox.tsx b/packages/client/src/components/combobox.tsx new file mode 100644 index 00000000000..ca632acbc92 --- /dev/null +++ b/packages/client/src/components/combobox.tsx @@ -0,0 +1,138 @@ +import { useState, useRef, useEffect } from 'react'; +import { Card } from '@/components/ui/card'; +import { Badge } from '@/components/ui/badge'; +import { ChevronDown, X } from 'lucide-react'; +import { formatAgentName } from '@/lib/utils'; + +interface Option { + icon: string; + label: string; + id?: string; +} + +interface MultiSelectComboboxProps { + options: Option[]; + className?: string; + onSelect?: (selected: Option[]) => void; + initialSelected?: Option[]; +} + +export default function MultiSelectCombobox({ + options = [], + className = '', + onSelect, + initialSelected = [], +}: MultiSelectComboboxProps) { + const [selected, setSelected] = useState(initialSelected); + const [isOpen, setIsOpen] = useState(false); + const comboboxRef = useRef(null); + + // Apply initialSelected when it changes + useEffect(() => { + if (initialSelected.length > 0) { + setSelected(initialSelected); + } + }, [initialSelected]); + + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (comboboxRef.current && !comboboxRef.current.contains(event.target as Node)) { + setIsOpen(false); + } + }; + + document.addEventListener('mousedown', handleClickOutside); + return () => document.removeEventListener('mousedown', handleClickOutside); + }, []); + + const toggleSelection = (option: Option) => { + setSelected((prev) => { + const newSelection = prev.some((item) => item.label === option.label) + ? prev.filter((item) => item.label !== option.label) + : [...prev, option]; + if (onSelect) onSelect(newSelection); + return newSelection; + }); + }; + + const removeSelection = (option: Option) => { + setSelected((prev) => { + const newSelection = prev.filter((item) => item.label !== option.label); + if (onSelect) onSelect(newSelection); + return newSelection; + }); + }; + + const removeExtraSelections = () => { + setSelected((prev) => { + const newSelection = prev.slice(0, 3); // Keep only the first 3 + if (onSelect) onSelect(newSelection); + return newSelection; + }); + }; + + return ( +
+
setIsOpen(!isOpen)} + > +
+ {selected.length > 0 ? ( + <> + {selected.slice(0, 3).map((item, index) => ( + + {item.label} + { + e.stopPropagation(); + removeSelection(item); + }} + /> + + ))} + {selected.length > 3 && ( + { + e.stopPropagation(); + removeExtraSelections(); + }} + > + +{selected.length - 3} more + + )} + + ) : ( + Select options... + )} +
+ +
+ {isOpen && ( + + {options.map((option, index) => ( +
item.label === option.label) ? 'bg-muted' : 'bg-card' + }`} + onClick={() => toggleSelection(option)} + > +
+ {option.icon ? ( + {option.label} + ) : ( + formatAgentName(option.label) + )} +
+ {option.label} +
+ ))} +
+ )} +
+ ); +} diff --git a/packages/client/src/components/group-panel.tsx b/packages/client/src/components/group-panel.tsx new file mode 100644 index 00000000000..787d05730be --- /dev/null +++ b/packages/client/src/components/group-panel.tsx @@ -0,0 +1,211 @@ +import { randomUUID } from '../lib/utils'; +import { Separator } from '@/components/ui/separator'; +import { GROUP_CHAT_SOURCE } from '@/constants'; +import { useRooms } from '@/hooks/use-query-hooks'; +import { apiClient } from '@/lib/api'; +import { type Agent, AgentStatus } from '@elizaos/core'; +import { useQueryClient } from '@tanstack/react-query'; +import { Loader2, Save, Trash, X } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { useNavigate } from 'react-router'; +import MultiSelectCombobox from './combobox'; +import { Button } from './ui/button'; +import { Card, CardContent, CardFooter, CardHeader, CardTitle } from './ui/card'; +import { Input } from './ui/input'; + +// Define the Option type to match what MultiSelectCombobox expects +interface Option { + icon: string; + label: string; + id?: string; // We'll add this to track agent IDs +} + +interface GroupPanel { + agents: Agent[] | undefined; + onClose: () => void; + groupId?: UUID; +} + +export default function GroupPanel({ onClose, agents, groupId }: GroupPanel) { + const [chatName, setChatName] = useState(''); + const [selectedAgents, setSelectedAgents] = useState([]); + const [creating, setCreating] = useState(false); + const [deleting, setDeleting] = useState(false); + const [initialOptions, setInitialOptions] = useState([]); + + const { data: roomsData } = useRooms(); + + const queryClient = useQueryClient(); + const navigate = useNavigate(); + + useEffect(() => { + if (groupId) { + const rooms = roomsData?.get(groupId); + if (!rooms || !rooms.length) { + return; + } + setChatName(rooms[0].name || ''); + + // Pre-select agents that are already in the room + if (agents) { + const roomAgentIds = rooms.map((room) => room.agentId).filter(Boolean); + const roomAgents = agents.filter((agent) => roomAgentIds.includes(agent.id)); + + setSelectedAgents(roomAgents); + + // Create initial options for the combobox + const options = roomAgents.map((agent) => ({ + icon: agent.settings?.avatar || '', + label: agent.name, + id: agent.id, + })); + + setInitialOptions(options); + } + } + }, [groupId, roomsData, agents]); + + // Create the options for the combobox + const getComboboxOptions = () => { + return ( + agents + ?.filter((agent) => agent.status === AgentStatus.ACTIVE) + .map((agent) => ({ + icon: agent.settings?.avatar || '', + label: agent.name, + id: agent.id, + })) || [] + ); + }; + return ( +
{ + if (e.key === 'Enter' || e.key === ' ') { + onClose(); + } + }} + > + e.stopPropagation()}> + + + {groupId ? 'Edit Group Chat' : 'Create Group Chat'} + + + + + + + +
+
+ + setChatName(e.target.value)} + className="w-full" + placeholder="Enter room name" + /> +
+ +
+ + { + if (agents) { + // Convert selected options back to Agent objects by matching on label (name) + const selectedAgentObjects = agents.filter((agent) => + selected.some((option) => option.label === agent.name) + ); + setSelectedAgents(selectedAgentObjects); + } + }} + className="w-full" + initialSelected={initialOptions} + /> +
+
+
+ + + {groupId && ( + + )} + + + +
+
+ ); +} diff --git a/packages/client/src/components/knowledge-manager.tsx b/packages/client/src/components/knowledge-manager.tsx new file mode 100644 index 00000000000..f1bbea282d3 --- /dev/null +++ b/packages/client/src/components/knowledge-manager.tsx @@ -0,0 +1,398 @@ +import type { UUID } from '@elizaos/core'; +import { Book, Clock, File, FileText, LoaderIcon, Trash2, Upload } from 'lucide-react'; +import { useCallback, useEffect, useRef, useState } from 'react'; +import { useAgentMemories, useDeleteMemory } from '../hooks/use-query-hooks'; +import { Badge } from './ui/badge'; +import { Button } from './ui/button'; +import { Card, CardFooter, CardHeader } from './ui/card'; + +import { useToast } from '@/hooks/use-toast'; +import { apiClient } from '@/lib/api'; +import { cn } from '@/lib/utils'; +import type { Memory } from '@elizaos/core'; +import { useQueryClient } from '@tanstack/react-query'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from './ui/dialog'; + +// Number of items to load per batch +const ITEMS_PER_PAGE = 10; + +interface MemoryContent { + text?: string; + metadata?: { + fileType?: string; + title?: string; + filename?: string; + path?: string; + description?: string; + }; +} + +interface MemoryMetadata { + type?: string; + title?: string; + filename?: string; + path?: string; + description?: string; + fileExt?: string; + timestamp?: number; +} + +export function KnowledgeManager({ agentId }: { agentId: UUID }) { + const [viewingContent, setViewingContent] = useState(null); + const [isUploading, setIsUploading] = useState(false); + const [visibleItems, setVisibleItems] = useState(ITEMS_PER_PAGE); + const [loadingMore, setLoadingMore] = useState(false); + const fileInputRef = useRef(null); + const scrollContainerRef = useRef(null); + const { toast } = useToast(); + const queryClient = useQueryClient(); + + // Use 'documents' table for knowledge + const tableName = 'documents'; + + const { data: memories = [], isLoading, error } = useAgentMemories(agentId, tableName); + const { mutate: deleteMemory } = useDeleteMemory(); + + // Handle scroll to implement infinite loading + const handleScroll = useCallback(() => { + if (!scrollContainerRef.current || loadingMore || visibleItems >= memories.length) { + return; + } + + const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current; + const scrolledToBottom = scrollTop + clientHeight >= scrollHeight - 100; // 100px buffer + + if (scrolledToBottom) { + setLoadingMore(true); + // Add a small delay to simulate loading and prevent too rapid updates + setTimeout(() => { + setVisibleItems((prev) => Math.min(prev + ITEMS_PER_PAGE, memories.length)); + setLoadingMore(false); + }, 300); + } + }, [loadingMore, visibleItems, memories.length]); + + // Reset visible items when filter changes or new data loads + useEffect(() => { + setVisibleItems(ITEMS_PER_PAGE); + }, []); + + // Set up scroll event listener + useEffect(() => { + const scrollContainer = scrollContainerRef.current; + if (scrollContainer) { + scrollContainer.addEventListener('scroll', handleScroll); + return () => scrollContainer.removeEventListener('scroll', handleScroll); + } + }, [handleScroll]); + + if (isLoading && (!memories || memories.length === 0)) { + return ( +
Loading knowledge documents...
+ ); + } + + if (error) { + return ( +
+ Error loading knowledge documents +
+ ); + } + + const formatDate = (timestamp: number) => { + const date = new Date(timestamp); + return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`; + }; + + const getFileIcon = (fileName: string) => { + const ext = fileName.split('.').pop()?.toLowerCase(); + + switch (ext) { + case 'md': + return ; + case 'js': + case 'ts': + case 'jsx': + case 'tsx': + return ; + case 'json': + return ; + default: + return ; + } + }; + + const handleDelete = (memoryId: string) => { + if (memoryId && window.confirm('Are you sure you want to delete this document?')) { + deleteMemory({ agentId, memoryId }); + setViewingContent(null); + } + }; + + const handleUploadClick = () => { + if (fileInputRef.current) { + fileInputRef.current.click(); + } + }; + + const handleFileChange = async (e: React.ChangeEvent) => { + const files = e.target.files; + if (!files || files.length === 0) return; + + setIsUploading(true); + + try { + const fileArray = Array.from(files); + const result = await apiClient.uploadKnowledge(agentId, fileArray); + + if (result.success) { + toast({ + title: 'Knowledge Uploaded', + description: `Successfully uploaded ${fileArray.length} file(s)`, + }); + + queryClient.invalidateQueries({ + queryKey: ['agents', agentId, 'memories', 'documents'], + }); + } + } catch (error) { + toast({ + title: 'Upload Failed', + description: error instanceof Error ? error.message : 'Failed to upload knowledge files', + variant: 'destructive', + }); + } finally { + setIsUploading(false); + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + } + }; + + // Get visible subset for infinite scrolling + const visibleMemories = memories.slice(0, visibleItems); + const hasMoreToLoad = visibleItems < memories.length; + + // Internal components for better organization + const LoadingIndicator = () => ( +
+ {loadingMore ? ( +
+ + Loading more... +
+ ) : ( + + )} +
+ ); + + const EmptyState = () => ( +
+ +

No knowledge documents yet

+ +
+ ); + + const KnowledgeCard = ({ memory, index }: { memory: Memory; index: number }) => { + const metadata = (memory.metadata as MemoryMetadata) || {}; + const title = metadata.title || memory.id || 'Unknown Document'; + const filename = metadata.filename || 'Unknown Document'; + const fileExt = metadata.fileExt || filename.split('.').pop()?.toLowerCase() || ''; + const displayName = title || filename; + const subtitle = metadata.path || filename; + + return ( + + )} +
+
+ + + + ); + }; + + return ( +
+
+
+

Knowledge Library

+ + +
+
+ +
+ {memories.length === 0 ? ( + + ) : ( +
+ {visibleMemories.map((memory: Memory, index: number) => ( + + ))} + {hasMoreToLoad && } +
+ )} +
+ + {/* Knowledge content dialog */} + !open && setViewingContent(null)}> + + + + {(() => { + const metadata = (viewingContent?.metadata as MemoryMetadata) || {}; + const filename = metadata.filename || 'Unknown Document'; + const title = metadata.title || filename; + + return ( + <> + {getFileIcon(filename)} + {title} + + ); + })()} + + + + Added on{' '} + {viewingContent + ? formatDate(viewingContent.createdAt || viewingContent.metadata?.timestamp || 0) + : ''} + + + +
+ {viewingContent && ( +
+                {viewingContent.content?.text}
+              
+ )} +
+ + + + + + +
+
+
+ ); +} diff --git a/packages/client/src/components/memory-edit-overlay.tsx b/packages/client/src/components/memory-edit-overlay.tsx index 2c939ef08c9..051808787a9 100644 --- a/packages/client/src/components/memory-edit-overlay.tsx +++ b/packages/client/src/components/memory-edit-overlay.tsx @@ -109,11 +109,15 @@ export default function MemoryEditOverlay({ }); } }; - return (
{ + if (e.key === 'Escape') { + onClose(); + } + }} > e.stopPropagation()}> diff --git a/packages/client/src/components/memory-viewer.tsx b/packages/client/src/components/memory-viewer.tsx index f3859694740..204e3f057ea 100644 --- a/packages/client/src/components/memory-viewer.tsx +++ b/packages/client/src/components/memory-viewer.tsx @@ -1,39 +1,13 @@ import type { UUID } from '@elizaos/core'; -import { - Book, - Clock, - Database, - File, - FileText, - Globe, - LoaderIcon, - MailCheck, - MessageSquareShare, - Pencil, - Trash2, - Upload, -} from 'lucide-react'; +import { Database, LoaderIcon, MailCheck, MessageSquareShare, Pencil } from 'lucide-react'; import { useCallback, useEffect, useRef, useState } from 'react'; import { useAgentMemories, useDeleteMemory } from '../hooks/use-query-hooks'; import { Badge } from './ui/badge'; import { Button } from './ui/button'; -import { Card, CardFooter, CardHeader } from './ui/card'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; -import { useToast } from '@/hooks/use-toast'; -import { apiClient } from '@/lib/api'; -import { cn } from '@/lib/utils'; import type { Memory } from '@elizaos/core'; -import { useQueryClient } from '@tanstack/react-query'; import MemoryEditOverlay from './memory-edit-overlay'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from './ui/dialog'; // Number of items to load per batch const ITEMS_PER_PAGE = 10; @@ -51,49 +25,42 @@ interface MemoryContent { description?: string; }; } - -interface MemoryMetadata { - type?: string; - title?: string; - filename?: string; - path?: string; - description?: string; - fileExt?: string; - timestamp?: number; +// Add type for message content structure based on API response +interface ChatMemoryContent extends MemoryContent { + text?: string; + actions?: string[]; + thought?: boolean; + inReplyTo?: string; + providers?: string[]; + channelType?: string; } enum MemoryType { all = 'all', - facts = 'facts', - knowledge = 'knowledge', - messagesSent = 'messagesSent', messagesReceived = 'messagesReceived', - messages = 'messages', + messagesSent = 'messagesSent', + thoughts = 'thoughts', + facts = 'facts', } -export function AgentMemoryViewer({ agentId }: { agentId: UUID }) { +export function AgentMemoryViewer({ agentId, agentName }: { agentId: UUID; agentName: string }) { const [selectedType, setSelectedType] = useState(MemoryType.all); const [editingMemory, setEditingMemory] = useState(null); - const [viewingContent, setViewingContent] = useState(null); - const [isUploading, setIsUploading] = useState(false); const [visibleItems, setVisibleItems] = useState(ITEMS_PER_PAGE); const [loadingMore, setLoadingMore] = useState(false); - const fileInputRef = useRef(null); const scrollContainerRef = useRef(null); - const { toast } = useToast(); - const queryClient = useQueryClient(); + + console.log({ agentName, agentId }); // Determine if we need to use the 'documents' table for knowledge const tableName = - selectedType === MemoryType.knowledge - ? 'documents' - : selectedType === MemoryType.facts - ? 'facts' - : selectedType === MemoryType.messagesSent || selectedType === MemoryType.messagesReceived - ? 'messages' - : selectedType === MemoryType.all - ? undefined - : undefined; + selectedType === MemoryType.facts + ? 'facts' + : selectedType === MemoryType.messagesSent || selectedType === MemoryType.messagesReceived + ? 'messages' + : selectedType === MemoryType.all + ? undefined + : undefined; const { data: memories = [], isLoading, error } = useAgentMemories(agentId, tableName); const { mutate: deleteMemory } = useDeleteMemory(); @@ -148,107 +115,51 @@ export function AgentMemoryViewer({ agentId }: { agentId: UUID }) { }; const getMemoryIcon = (memory: Memory, content: MemoryContent) => { - if (selectedType === MemoryType.knowledge) return ; - if (selectedType === MemoryType.facts) return ; if (memory.entityId === memory.agentId) return ; if (memory.entityId !== memory.agentId) return ; if (content?.thought) return ; return ; }; - const getMemoryLabel = (memoryType: string | undefined, content: MemoryContent) => { - if (selectedType === MemoryType.knowledge) return 'Knowledge'; - if (selectedType === MemoryType.facts) return 'Facts'; - if (content?.thought) return 'Messages Sent'; - if (!content?.thought) return 'Messages Received'; - return memoryType || 'Memory'; - }; - - const getFileIcon = (fileName: string) => { - const ext = fileName.split('.').pop()?.toLowerCase(); - - switch (ext) { - case 'md': - return ; - case 'js': - case 'ts': - case 'jsx': - case 'tsx': - return ; - case 'json': - return ; - default: - return ; - } - }; - const handleDelete = (memoryId: string) => { if (memoryId && window.confirm('Are you sure you want to delete this memory entry?')) { deleteMemory({ agentId, memoryId }); - setViewingContent(null); - } - }; - - const handleUploadClick = () => { - if (fileInputRef.current) { - fileInputRef.current.click(); } }; - const handleFileChange = async (e: React.ChangeEvent) => { - const files = e.target.files; - if (!files || files.length === 0) return; - - setIsUploading(true); + // Group messages by date for better organization + const groupMessagesByDate = (messages: Memory[]) => { + const groups: Record = {}; - try { - const fileArray = Array.from(files); - const result = await apiClient.uploadKnowledge(agentId, fileArray); + for (const memory of messages) { + const date = new Date(memory.createdAt || 0); + const dateKey = date.toLocaleDateString(); - if (result.success) { - toast({ - title: 'Knowledge Uploaded', - description: `Successfully uploaded ${fileArray.length} file(s)`, - }); - - queryClient.invalidateQueries({ - queryKey: ['agents', agentId, 'memories', 'documents'], - }); - } - } catch (error) { - toast({ - title: 'Upload Failed', - description: error instanceof Error ? error.message : 'Failed to upload knowledge files', - variant: 'destructive', - }); - } finally { - setIsUploading(false); - if (fileInputRef.current) { - fileInputRef.current.value = ''; + if (!groups[dateKey]) { + groups[dateKey] = []; } + groups[dateKey].push(memory); } + + return groups; }; + // Filter memories based on selected type const filteredMemories = memories.filter((memory: Memory) => { if (selectedType === MemoryType.all) { - const content = memory.content as MemoryContent; - return !(content?.channelType === 'knowledge' || memory.metadata?.type === 'knowledge'); + return true; } - if (selectedType === MemoryType.knowledge) return true; - const content = memory.content as MemoryContent; + const content = memory.content as ChatMemoryContent; - if (selectedType === MemoryType.messages) { - return !( - content?.thought || - content?.channelType === 'thought' || - memory.metadata?.type === 'thought' - ); + if (selectedType === MemoryType.thoughts) { + return content?.thought !== undefined; } if (selectedType === MemoryType.messagesSent) { return memory.entityId === memory.agentId; } + if (selectedType === MemoryType.messagesReceived) { return memory.entityId !== memory.agentId; } @@ -260,6 +171,8 @@ export function AgentMemoryViewer({ agentId }: { agentId: UUID }) { const visibleMemories = filteredMemories.slice(0, visibleItems); const hasMoreToLoad = visibleItems < filteredMemories.length; + const messageGroups = groupMessagesByDate(visibleMemories); + // Internal components for better organization const LoadingIndicator = () => (
@@ -282,110 +195,43 @@ export function AgentMemoryViewer({ agentId }: { agentId: UUID }) { ); const EmptyState = () => ( -
- {selectedType === 'knowledge' ? ( - <> - -

No knowledge documents yet

- - - ) : ( - <>No memories recorded yet - )} +
+ +

No Memories

+

+ Messages will appear here once the agent begins communicating. +

); - const KnowledgeCard = ({ memory, index }: { memory: Memory; index: number }) => { - const metadata = (memory.metadata as MemoryMetadata) || {}; - const title = metadata.title || memory.id || 'Unknown Document'; - const filename = metadata.filename || 'Unknown Document'; - const fileExt = metadata.fileExt || filename.split('.').pop()?.toLowerCase() || ''; - const displayName = title || filename; - const subtitle = metadata.path || filename; - - return ( - - )} -
-
- -
- - ); - }; + // Get entity name with improved logic + const entityName = memory.metadata?.entityName ? memory.metadata?.entityName : agentName; - const MemoryCard = ({ memory, index }: { memory: Memory; index: number }) => { - const memoryType = memory.metadata?.type || 'Memory'; - const content = memory.content as MemoryContent; - const source = content?.source; + console.log(entityName, memory.id, agentName); return (
+ {/* Action buttons */} {memory.id && (
-
)} -
- - {getMemoryIcon(memory, content)} {getMemoryLabel(memoryType, content)} - + {/* Memory header - Author and timestamp */} +
- {source && ( - - {source} + + {getMemoryIcon(memory, content)} + {entityName} + + {content?.actions && content.actions.length > 0 && ( + + {content.actions.join(', ')} )} - - {formatDate(memory.createdAt || 0)} -
+ + {timestamp} +
-
+ {/* Message content */} + {content?.text && ( +
+

{content.text}

+
+ )} + + {/* Thought content */} + {hasThought && ( +
+
+ + Thought Process +
+
+

{content.thought}

+
+
+ )} + + {/* Show providers if available */} + {content?.providers && content.providers.length > 0 && ( +
+
+ Providers +
+
+ {content.providers.map((provider) => ( + + {provider} + + ))} +
+
+ )} + + {/* Memory metadata */} +
{memory.id && ( -
- ID: - {memory.id} +
+ ID: + {memory.id}
)} - {memory.content && ( -
- Content: - {typeof memory.content === 'object' - ? JSON.stringify(memory.content, null, 2) - : memory.content} + {content?.inReplyTo && ( +
+ In Reply To: + {content.inReplyTo}
)} {memory.metadata && Object.keys(memory.metadata).length > 0 && ( -
- Metadata: - {typeof memory.metadata === 'object' - ? JSON.stringify(memory.metadata, null, 2) - : memory.metadata} -
+
+ + Metadata + +
+
+                  {JSON.stringify(memory.metadata, null, 2)}
+                
+
+
)}
@@ -458,149 +334,67 @@ export function AgentMemoryViewer({ agentId }: { agentId: UUID }) { }; return ( -
-
+
+
-

- {selectedType === 'knowledge' ? 'Knowledge Library' : 'Agent Memories'} -

- {selectedType === 'knowledge' && ( - +

Memories

+ {!isLoading && ( + + {filteredMemories.length} memories + )} -
- +
+ +
{filteredMemories.length === 0 ? ( ) : (
- {/* Knowledge memories */} - {selectedType === 'knowledge' && ( -
- {visibleMemories.map((memory: Memory, index: number) => ( - - ))} - {hasMoreToLoad && } -
- )} - - {/* Regular memories */} - {selectedType !== 'knowledge' && ( -
- {visibleMemories.map((memory: Memory, index: number) => ( - - ))} - {hasMoreToLoad && } + {/* Group messages by date */} + {Object.entries(messageGroups).map(([date, messages]) => ( +
+
+ + {date} + +
+
+ {messages.map((memory: Memory, index: number) => ( + + ))} +
- )} + ))} + {hasMoreToLoad && }
)}
- {/* Knowledge content dialog */} - !open && setViewingContent(null)}> - - - - {(() => { - const metadata = (viewingContent?.metadata as MemoryMetadata) || {}; - const filename = metadata.filename || 'Unknown Document'; - const title = metadata.title || filename; - - return ( - <> - {getFileIcon(filename)} - {title} - - ); - })()} - - - - Added on{' '} - {viewingContent - ? formatDate(viewingContent.createdAt || viewingContent.metadata?.timestamp || 0) - : ''} - - - -
- {viewingContent && ( -
-                {viewingContent.content?.text}
-              
- )} -
- - - - - - -
-
- {editingMemory && ( (null); - const [isDropdownOpen, setIsDropdownOpen] = useState(false); - // handle Start/Stop button - let buttonLabel = 'Start'; - let buttonIcon = ; + // Button state configuration + const buttonConfig = { + label: isActive ? 'Stop' : 'Start', + icon: isActive ? : , + variant: isActive ? 'destructive' : 'default', + }; + if (isStarting) { - buttonLabel = 'Starting...'; - buttonIcon = ; + buttonConfig.label = 'Starting...'; + buttonConfig.icon = ; } else if (isStopping) { - buttonLabel = 'Stopping...'; - buttonIcon = ; - } else if (isActive) { - buttonLabel = 'Stop'; - buttonIcon = ; + buttonConfig.label = 'Stopping...'; + buttonConfig.icon = ; } - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { - setIsDropdownOpen(false); - } - }; + // Handle agent start/stop + const handleAgentToggle = () => { + if (isProcessing) return; + + if (!isActive) { + startAgent(agent); + } else { + stopAgent(agent); + } + }; - document.addEventListener('mousedown', handleClickOutside); - return () => { - document.removeEventListener('mousedown', handleClickOutside); - }; - }, []); + // Navigate to settings + const navigateToSettings = () => { + navigate(`/settings/${agent.id}`); + }; return (
{ + if (e.key === 'Enter' || e.key === ' ') { + onClose(); + } + }} > e.stopPropagation()} > -
-
-
-
- {agent && ( -
+ +
+ +
+ +
+
+
+
+
{agent.settings?.avatar ? ( Agent Avatar ) : ( formatAgentName(agent.name) )}
- )} -
-
-
- {agent &&
{agent.name}
} +
+
+
+
{agent.name}
+
+ + + { + e.stopPropagation(); + if (agent.id) { + navigator.clipboard.writeText(agent.id); + } + }} + onKeyUp={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.stopPropagation(); + if (agent.id) { + navigator.clipboard.writeText(agent.id); + } + } + }} + > + ID: {agent.id ?? 'N/A'} + + + +

Click to copy agent ID

+
+
+
+
+
+ -
-
- - - - - +
+
+

Status

+
+
+ {isActive ? 'Active' : 'Inactive'}
-
-
- -
-
-
-
-

About Me

- {agent &&

{agent?.system}

} -
+ +
+

Created

+

+ {agent?.createdAt + ? new Date(agent.createdAt).toLocaleDateString() + : new Date().toLocaleDateString()} +

+
+ +
+

Plugins

+
+ {agent?.plugins?.length > 0 ? ( + agent.plugins.map((plugin, index) => { + // Extract plugin name by removing the prefix + const pluginName = plugin + .replace('@elizaos/plugin-', '') + .replace('@elizaos-plugins/plugin-', ''); + return ( + + {pluginName} + + ); + }) + ) : ( +

No plugins enabled

+ )}
+ + +
+ + + +
+ + {isActive && ( + + )} +
); diff --git a/packages/client/src/components/room.tsx b/packages/client/src/components/room.tsx new file mode 100644 index 00000000000..5bb06076fb3 --- /dev/null +++ b/packages/client/src/components/room.tsx @@ -0,0 +1,601 @@ +import { Button } from '@/components/ui/button'; +import { + ChatBubble, + ChatBubbleMessage, + ChatBubbleTimestamp, +} from '@/components/ui/chat/chat-bubble'; +import { ChatInput } from '@/components/ui/chat/chat-input'; +import { ChatMessageList } from '@/components/ui/chat/chat-message-list'; +import { GROUP_CHAT_SOURCE, USER_NAME } from '@/constants'; +import { useAgents, useGroupMessages, useRooms } from '@/hooks/use-query-hooks'; +import SocketIOManager from '@/lib/socketio-manager'; +import { getEntityId, moment } from '@/lib/utils'; +import { WorldManager } from '@/lib/world-manager'; +import type { IAttachment } from '@/types'; +import type { Agent, Content, UUID } from '@elizaos/core'; +import { AgentStatus } from '@elizaos/core'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@radix-ui/react-collapsible'; +import { useQueryClient } from '@tanstack/react-query'; +import { ChevronRight, Edit, Paperclip, Send, X } from 'lucide-react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; +import AIWriter from 'react-aiwriter'; +import { Avatar, AvatarImage } from './ui/avatar'; +import { Badge } from './ui/badge'; +import ChatTtsButton from './ui/chat/chat-tts-button'; +import { useAutoScroll } from './ui/chat/hooks/useAutoScroll'; +import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip'; +import AgentAvatarStack from './agent-avatar-stack'; +import GroupPanel from './group-panel'; + +type ExtraContentFields = { + name: string; + createdAt: number; + isLoading?: boolean; +}; + +type ContentWithUser = Content & ExtraContentFields; + +const MemoizedMessageContent = React.memo(MessageContent); + +function MessageContent({ + message, + isLastMessage, + isUser, +}: { + message: ContentWithUser; + isLastMessage: boolean; + isUser: boolean; +}) { + // Only log message details in development mode + if (import.meta.env.DEV) { + console.log(`[Chat] Rendering message from ${message.name}:`, { + isUser: isUser, + text: message.text?.substring(0, 20) + '...', + senderId: message.senderId, + source: message.source, + }); + } + + return ( +
+ + {!isUser && ( +
+ {message.text && message.thought && ( + + + + Thought Process + + + + {message.thought} + + + + )} +
+ )} + +
+ {isUser ? ( + message.text + ) : isLastMessage && !isUser ? ( + {message.text} + ) : ( + message.text + )} +
+ {!message.text && message.thought && ( +
+ {isUser ? ( + message.thought + ) : isLastMessage && !isUser ? ( + + {message.thought} + + ) : ( + {message.thought} + )} +
+ )} + + {message.attachments?.map((attachment: IAttachment) => ( +
+ attachment +
+ + +
+
+ ))} + {message.text && message.createdAt && ( + + )} +
+ {!isUser && ( +
+
+ {message.text && !message.isLoading ? ( +
+ +
+ ) : ( +
+ )} +
+
+ {message.text && message.actions && ( + + {message.actions} + + )} +
+
+ )} +
+ ); +} + +export default function Page({ serverId }: { serverId: UUID }) { + const [selectedFile, setSelectedFile] = useState(null); + const [input, setInput] = useState(''); + const [showGroupPanel, setShowGroupPanel] = useState(false); + const inputRef = useRef(null); + const fileInputRef = useRef(null); + const formRef = useRef(null); + const queryClient = useQueryClient(); + const worldId = WorldManager.getWorldId(); + + const { data: roomsData } = useRooms(); + const entityId = getEntityId(); + + const { data: messages = [] } = useGroupMessages(serverId, GROUP_CHAT_SOURCE); + + const socketIOManager = SocketIOManager.getInstance(); + + const { data: { data: agentsData } = {}, isLoading, isError } = useAgents(); + const agents = agentsData?.agents || []; + + const prevServerIdRef = useRef(null); + const prevActiveAgentIdsRef = useRef([]); + + const getAvatar = (agentId: string): string | null => { + const rooms = roomsData?.get(serverId); + const room = rooms?.find((room) => room.agentId === agentId); + const agent = room?.character; + const avatar = agent?.settings?.avatar; + return typeof avatar === 'string' ? avatar : null; + }; + + const getRoomName = () => { + const rooms = roomsData?.get(serverId); + if (rooms && rooms.length) { + return rooms[0].name; + } + + return null; + }; + + useEffect(() => { + if (isLoading || isError || !agents || !agents.length || !roomsData) { + return; + } + let activeAgentIds: UUID[] = []; + + const roomDatas = roomsData.get(serverId); + if (roomDatas) { + for (const roomData of roomDatas) { + const agentData = agents.find((agent) => agent.id === roomData.agentId); + if (agentData) { + if (agentData.status === AgentStatus.ACTIVE) { + activeAgentIds.push(roomData.agentId as UUID); + } + } + } + } + + const isSameServer = prevServerIdRef.current === serverId; + const isSameAgents = + activeAgentIds.length === prevActiveAgentIdsRef.current.length && + activeAgentIds.every((id, index) => id === prevActiveAgentIdsRef.current[index]); + + if (isSameServer && isSameAgents) { + return; // No changes, avoid reconnecting + } + + // Update refs + prevServerIdRef.current = serverId; + prevActiveAgentIdsRef.current = activeAgentIds; + + socketIOManager.initialize(entityId, activeAgentIds); + + // Join the room for this agent + socketIOManager.joinRoom(serverId); + + console.log(`[Chat] Joined room ${serverId} with entityId ${entityId}`); + + const handleMessageBroadcasting = (data: ContentWithUser) => { + console.log(`[Chat] Received message broadcast:`, data); + + // Skip messages that don't have required content + if (!data) { + console.warn('[Chat] Received empty or invalid message data:', data); + return; + } + + // Skip messages not for this room + if (data.roomId !== serverId) { + console.log( + `[Chat] Ignoring message for different room: ${data.roomId}, we're in ${serverId}` + ); + return; + } + + // Check if the message is from the current user or from the agent + const isCurrentUser = data.senderId === entityId; + + // Build a proper ContentWithUser object that matches what the messages query expects + const newMessage: ContentWithUser = { + ...data, + // Set the correct name based on who sent the message + name: isCurrentUser ? USER_NAME : (data.senderName as string), + createdAt: data.createdAt || Date.now(), + isLoading: false, + }; + + console.log(`[Chat] Adding new message to UI from ${newMessage.name}:`, newMessage); + + // Update the message list without triggering a re-render cascade + queryClient.setQueryData( + ['groupmessages', serverId, worldId], + (old: ContentWithUser[] = []) => { + console.log(`[Chat] Current messages:`, old?.length || 0); + + // Check if this message is already in the list (avoid duplicates) + const isDuplicate = old.some( + (msg) => + msg.text === newMessage.text && + msg.name === newMessage.name && + Math.abs((msg.createdAt || 0) - (newMessage.createdAt || 0)) < 5000 // Within 5 seconds + ); + + if (isDuplicate) { + console.log('[Chat] Skipping duplicate message'); + return old; + } + + return [...old, newMessage]; + } + ); + + // Remove the redundant state update that was causing render loops + // setInput(prev => prev + ''); + }; + + // Add listener for message broadcasts + console.log(`[Chat] Adding messageBroadcast listener`); + socketIOManager.on('messageBroadcast', handleMessageBroadcasting); + + return () => { + // When leaving this chat, leave the room but don't disconnect + console.log(`[Chat] Leaving room ${serverId}`); + socketIOManager.leaveRoom(serverId); + socketIOManager.off('messageBroadcast', handleMessageBroadcasting); + prevServerIdRef.current = null; + prevActiveAgentIdsRef.current = []; + }; + }, [isLoading, isError, agents, roomsData, serverId]); + + // Use a stable ID for refs to avoid excessive updates + const scrollRefId = useRef(`scroll-${Math.random().toString(36).substring(2, 9)}`).current; + + const { scrollRef, isAtBottom, scrollToBottom, disableAutoScroll } = useAutoScroll({ + smooth: true, + }); + + // Use a ref to track the previous message count to avoid excessive scrolling + const prevMessageCountRef = useRef(0); + + // Update scroll without creating a circular dependency + const safeScrollToBottom = useCallback(() => { + // Add a small delay to avoid render loops + setTimeout(() => { + scrollToBottom(); + }, 0); + }, []); + + useEffect(() => { + // Only scroll if the message count has changed + if (messages.length !== prevMessageCountRef.current) { + console.log(`[Chat][${scrollRefId}] Messages updated, scrolling to bottom`); + safeScrollToBottom(); + prevMessageCountRef.current = messages.length; + } + }, [messages.length, safeScrollToBottom, scrollRefId]); + + useEffect(() => { + safeScrollToBottom(); + }, [safeScrollToBottom]); + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + if (e.nativeEvent.isComposing) return; + handleSendMessage(e as unknown as React.FormEvent); + } + }; + + const handleSendMessage = (e: React.FormEvent) => { + e.preventDefault(); + if (!input) return; + + // Always add the user's message immediately to the UI before sending it to the server + const userMessage: ContentWithUser = { + text: input, + name: USER_NAME, + createdAt: Date.now(), + senderId: entityId, + senderName: USER_NAME, + roomId: serverId, + source: GROUP_CHAT_SOURCE, + id: crypto.randomUUID(), // Add a unique ID for React keys and duplicate detection + }; + + console.log('[Chat] Adding user message to UI:', userMessage); + + // Update the local message list first for immediate feedback + queryClient.setQueryData( + ['groupmessages', serverId, worldId], + (old: ContentWithUser[] = []) => { + // Check if exact same message exists already to prevent duplicates + const exists = old.some( + (msg) => + msg.text === userMessage.text && + msg.name === USER_NAME && + Math.abs((msg.createdAt || 0) - userMessage.createdAt) < 1000 + ); + + if (exists) { + console.log('[Chat] Skipping duplicate user message'); + return old; + } + + return [...old, userMessage]; + } + ); + + // We don't need to call scrollToBottom here, the message count change will trigger it + // via the useEffect hook + + // Send the message to the server/agent + socketIOManager.sendMessage(input, serverId, GROUP_CHAT_SOURCE); + + setSelectedFile(null); + setInput(''); + formRef.current?.reset(); + }; + + useEffect(() => { + if (inputRef.current) { + inputRef.current.focus(); + } + }, []); + + const handleFileChange = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (file?.type.startsWith('image/')) { + setSelectedFile(file); + } + }; + + // Sort agents: enabled first, then disabled + const sortedAgents = [...agents] + .filter((agent) => roomsData?.get(serverId)?.some((room) => room.agentId === agent.id)) + .sort((a, b) => { + // Sort by status (active agents first) + if (a.status === AgentStatus.ACTIVE && b.status !== AgentStatus.ACTIVE) return -1; + if (a.status !== AgentStatus.ACTIVE && b.status === AgentStatus.ACTIVE) return 1; + // If both have the same status, sort alphabetically by name + return a.name.localeCompare(b.name); + }); + + // Split into enabled and disabled groups + const activeAgents = sortedAgents.filter( + (agent: Partial) => agent.status === AgentStatus.ACTIVE + ); + const inactiveAgents = sortedAgents.filter( + (agent: Partial) => agent.status === AgentStatus.INACTIVE + ); + + // Create a map of agent avatars for easy lookup + const agentAvatars: Record = {}; + agents.forEach((agent) => { + if (agent.id && agent.settings?.avatar) { + agentAvatars[agent.id] = agent.settings.avatar; + } + }); + + // Get all agent IDs for this room + const getRoomAgentIds = () => { + const rooms = roomsData?.get(serverId); + if (rooms && rooms.length) { + return rooms.map((room) => room.agentId).filter(Boolean) as UUID[]; + } + return []; + }; + + const roomArray = roomsData?.get(serverId); + const roomAgentNames = roomArray?.map((room) => room.character.name).filter(Boolean) as string[]; + + return ( +
+
+ {/* Agent Header */} +
+
+ +
+
+

{getRoomName() || 'Group Chat'}

+
+
+
+ +
+ +
+ {/* Main Chat Area */} +
+ {/* Chat Messages */} + + {messages.map((message: ContentWithUser, index: number) => { + const isUser = message.name === USER_NAME; + + return ( +
+ + {message.text && !isUser && ( + + + + )} + + + +
+ ); + })} +
+ + {/* Chat Input */} +
+
+ {selectedFile ? ( +
+
+ + Selected file +
+
+ ) : null} + setInput(target.value)} + placeholder="Type your message here..." + className="min-h-12 resize-none rounded-md bg-card border-0 p-3 shadow-none focus-visible:ring-0" + /> +
+ + +
+ + +
+
+ +

Attach file

+
+
+ +
+ +
+
+
+
+ + {showGroupPanel && ( + setShowGroupPanel(false)} groupId={serverId} /> + )} +
+ ); +} diff --git a/packages/client/src/components/ui/dropdown-menu.tsx b/packages/client/src/components/ui/dropdown-menu.tsx new file mode 100644 index 00000000000..bd692bdf57a --- /dev/null +++ b/packages/client/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,188 @@ +'use client'; + +import * as React from 'react'; +import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'; +import { Check, ChevronRight, Circle } from 'lucide-react'; + +import { cn } from '@/lib/utils'; + +const DropdownMenu = DropdownMenuPrimitive.Root; + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; + +const DropdownMenuGroup = DropdownMenuPrimitive.Group; + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal; + +const DropdownMenuSub = DropdownMenuPrimitive.Sub; + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)); +DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName; + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName; + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)); +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, ...props }, ref) => ( + svg]:size-4 [&>svg]:shrink-0', + inset && 'pl-8', + className + )} + {...props} + /> +)); +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)); +DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName; + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)); +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName; + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, ...props }, ref) => ( + +)); +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; + +const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes) => { + return ( + + ); +}; +DropdownMenuShortcut.displayName = 'DropdownMenuShortcut'; + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +}; diff --git a/packages/client/src/components/ui/resizable.tsx b/packages/client/src/components/ui/resizable.tsx new file mode 100644 index 00000000000..60979c03a39 --- /dev/null +++ b/packages/client/src/components/ui/resizable.tsx @@ -0,0 +1,42 @@ +'use client'; + +import { GripVertical } from 'lucide-react'; +import * as ResizablePrimitive from 'react-resizable-panels'; + +import { cn } from '@/lib/utils'; + +const ResizablePanelGroup = ({ + className, + ...props +}: React.ComponentProps) => ( + +); + +const ResizablePanel = ResizablePrimitive.Panel; + +const ResizableHandle = ({ + withHandle, + className, + ...props +}: React.ComponentProps & { + withHandle?: boolean; +}) => ( + div]:rotate-90', + className + )} + {...props} + > + {withHandle && ( +
+ +
+ )} +
+); + +export { ResizablePanelGroup, ResizablePanel, ResizableHandle }; diff --git a/packages/client/src/constants.ts b/packages/client/src/constants.ts index 68cc6c6a69a..f43ddd77a24 100644 --- a/packages/client/src/constants.ts +++ b/packages/client/src/constants.ts @@ -1 +1,5 @@ export const USER_NAME = 'user'; +export const CHAT_SOURCE = 'client_chat'; +export const GROUP_CHAT_SOURCE = 'client_group_chat'; + +export const AVATAR_IMAGE_MAX_SIZE = 300; diff --git a/packages/client/src/hooks/use-query-hooks.ts b/packages/client/src/hooks/use-query-hooks.ts index a30c78211cc..c2d518c009c 100644 --- a/packages/client/src/hooks/use-query-hooks.ts +++ b/packages/client/src/hooks/use-query-hooks.ts @@ -1,7 +1,7 @@ -import { USER_NAME } from '@/constants'; +import { GROUP_CHAT_SOURCE, USER_NAME } from '@/constants'; import { apiClient } from '@/lib/api'; import { WorldManager } from '@/lib/world-manager'; -import type { Agent, Content, Memory, UUID } from '@elizaos/core'; +import type { Agent, Content, Memory, UUID, Room } from '@elizaos/core'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useState } from 'react'; import { useToast } from './use-toast'; @@ -430,6 +430,78 @@ export function useMessages( }; } +export function useGroupMessages( + serverId: UUID, + groupChatSource: string +): { + data: ContentWithUser[] | undefined; + isLoading: boolean; + isError: boolean; + error: unknown; +} { + const worldId = WorldManager.getWorldId(); + + // Initial fetch of messages + const messagesQuery = useQuery({ + queryKey: ['groupmessages', serverId, worldId], + queryFn: async () => { + const result = await apiClient.getGroupMemories(serverId); + const validSuffixes = [`:${USER_NAME}`, ':agent']; + let memories = result.data + .map((memory: Memory): ContentWithUser | null => { + const source = memory.content?.source ?? ''; + if ( + !source.startsWith(groupChatSource) || + !validSuffixes.some((suffix) => source.endsWith(suffix)) + ) { + return null; + } + const isUser = source.endsWith(validSuffixes[0]); + + return { + text: memory.content.text, + roomId: memory.roomId, + name: isUser ? USER_NAME : 'agent', + agentId: memory.agentId, + entityId: memory.entityId, + createdAt: memory.createdAt || 0, + attachments: memory.content.attachments, + source: memory.content.source, + worldId, + id: memory.id, + thought: memory.content.thought, + }; + }) + .filter(Boolean); // Remove null values from the array + + const uniqueMessages = new Map(); + + memories = memories.filter((msg: Memory) => { + if (msg.name === USER_NAME) { + const key = msg.text; + if (uniqueMessages.has(key) && uniqueMessages.get(key) !== msg.agentId) { + // If there's already a message with the same text but different agentId, filter it out + return false; + } + uniqueMessages.set(key, msg.agentId); + } + return true; + }); + + // Sort messages by createdAt timestamp + memories.sort((a: Memory, b: Memory) => (a.createdAt ?? 0) - (b.createdAt ?? 0)); + + return memories; + }, + enabled: Boolean(serverId && groupChatSource), + staleTime: STALE_TIMES.FREQUENT, + }); + + return { + ...messagesQuery, + }; +} + // Hook for fetching agent actions /** * Custom hook to fetch agent actions for a specific agent and room. @@ -614,3 +686,32 @@ export function useUpdateMemory() { }, }); } + +export function useRooms(options = {}) { + const network = useNetworkStatus(); + + return useQuery>({ + queryKey: ['rooms'], + queryFn: async () => { + const rooms = await apiClient.getRooms(); + const worldRooms = rooms.data.filter( + (room: Room) => + room.worldId === WorldManager.getWorldId() && room.source === GROUP_CHAT_SOURCE + ); + + const roomMap: Map = new Map(); + for (const room of worldRooms) { + const { serverId, ...rest } = room; + if (serverId) { + roomMap.set(serverId, [...(roomMap.get(serverId) || []), { serverId, ...rest }]); + } + } + + return roomMap; + }, + staleTime: STALE_TIMES.FREQUENT, + refetchInterval: !network.isOffline ? STALE_TIMES.FREQUENT : false, + refetchIntervalInBackground: false, + ...options, + }); +} diff --git a/packages/client/src/lib/api.ts b/packages/client/src/lib/api.ts index 6e281558e30..3afb578af4d 100644 --- a/packages/client/src/lib/api.ts +++ b/packages/client/src/lib/api.ts @@ -298,7 +298,15 @@ export const apiClient = { }, // Room-related routes - getRooms: (agentId: string) => { + getRooms: () => { + const worldId = WorldManager.getWorldId(); + return fetcher({ + url: `/world/${worldId}/rooms`, + method: 'GET', + }); + }, + + getRoomsForParticipant: (agentId: string) => { const worldId = WorldManager.getWorldId(); return fetcher({ url: `/agents/${agentId}/rooms`, @@ -462,4 +470,40 @@ export const apiClient = { body: formData, }); }, + + getGroupMemories: (serverId: UUID) => { + const worldId = WorldManager.getWorldId(); + return fetcher({ + url: `/world/${worldId}/memories/${serverId}`, + method: 'GET', + }); + }, + + createGroupChat: ( + agentIds: string[], + roomName: string, + serverId: string, + source: string, + metadata?: any + ) => { + const worldId = WorldManager.getWorldId(); + return fetcher({ + url: `/agents/groups/${serverId}`, + method: 'POST', + body: { + agentIds, + name: roomName, + worldId, + source, + metadata, + }, + }); + }, + + deleteGroupChat: (serverId: string) => { + return fetcher({ + url: `/agents/groups/${serverId}`, + method: 'DELETE', + }); + }, }; diff --git a/packages/client/src/lib/socketio-manager.ts b/packages/client/src/lib/socketio-manager.ts index 83f02e82590..85ceafb8150 100644 --- a/packages/client/src/lib/socketio-manager.ts +++ b/packages/client/src/lib/socketio-manager.ts @@ -20,6 +20,7 @@ class SocketIOManager extends EventEmitter { private resolveConnect: (() => void) | null = null; private activeRooms: Set = new Set(); private entityId: string | null = null; + private agentIds: string[] | null = null; private constructor() { super(); @@ -36,14 +37,15 @@ class SocketIOManager extends EventEmitter { * Initialize the Socket.io connection to the server * @param entityId The client entity ID */ - public initialize(entityId: string): void { + public initialize(entityId: string, agentIds: string[]): void { + this.entityId = entityId; + this.agentIds = agentIds; + if (this.socket) { console.warn('[SocketIO] Socket already initialized'); return; } - this.entityId = entityId; - // Create a single socket connection const fullURL = window.location.origin + '/'; console.log('connecting to', fullURL); @@ -99,6 +101,19 @@ class SocketIOManager extends EventEmitter { if (this.activeRooms.has(data.roomId)) { console.log(`[SocketIO] Handling message for active room ${data.roomId}`); this.emit('messageBroadcast', data); + if (this.socket) { + this.socket.emit('message', { + type: SOCKET_MESSAGE_TYPE.SEND_MESSAGE, + payload: { + senderId: data.senderId, + senderName: data.senderName, + message: data.text, + roomId: data.roomId, + worldId: WorldManager.getWorldId(), + source: data.source, + }, + }); + } } else { console.warn( `[SocketIO] Received message for inactive room ${data.roomId}, active rooms:`, @@ -147,6 +162,7 @@ class SocketIOManager extends EventEmitter { payload: { roomId, entityId: this.entityId, + agentIds: this.agentIds, }, }); diff --git a/packages/client/src/lib/utils.ts b/packages/client/src/lib/utils.ts index 52f6f5a4b88..848bfd2dd94 100644 --- a/packages/client/src/lib/utils.ts +++ b/packages/client/src/lib/utils.ts @@ -1,3 +1,4 @@ +import { AVATAR_IMAGE_MAX_SIZE } from '@/constants'; import type { UUID } from '@elizaos/core'; import { type ClassValue, clsx } from 'clsx'; import dayjs from 'dayjs'; @@ -59,3 +60,47 @@ export function getEntityId(): UUID { return newUserId; } + +export const compressImage = ( + file: File, + maxSize = AVATAR_IMAGE_MAX_SIZE, + quality = 0.8 +): Promise => { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = (e) => { + if (e.target?.result) { + const img = new Image(); + img.src = e.target.result as string; + img.onload = () => { + const canvas = document.createElement('canvas'); + let width = img.width; + let height = img.height; + + if (width > height) { + if (width > maxSize) { + height *= maxSize / width; + width = maxSize; + } + } else { + if (height > maxSize) { + width *= maxSize / height; + height = maxSize; + } + } + + canvas.width = width; + canvas.height = height; + const ctx = canvas.getContext('2d'); + ctx?.drawImage(img, 0, 0, width, height); + const resizedBase64 = canvas.toDataURL('image/jpeg', quality); + + resolve(resizedBase64); + }; + img.onerror = reject; + } + }; + reader.onerror = reject; + reader.readAsDataURL(file); + }); +}; diff --git a/packages/client/src/routes/chat.tsx b/packages/client/src/routes/chat.tsx index 957b06f5167..2b1db4f01ad 100644 --- a/packages/client/src/routes/chat.tsx +++ b/packages/client/src/routes/chat.tsx @@ -1,12 +1,49 @@ -import Chat from '@/components/chat'; -import type { UUID } from '@elizaos/core'; +import { useAgent } from '@/hooks/use-query-hooks'; +import { WorldManager } from '@/lib/world-manager'; +import { useState } from 'react'; import { useParams } from 'react-router'; +import Chat from '@/components/chat'; +import { AgentSidebar } from '../components/agent-sidebar'; +import type { UUID, Agent } from '@elizaos/core'; +import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '../components/ui/resizable'; + export default function AgentRoute() { + const [showDetails, setShowDetails] = useState(false); + const worldId = WorldManager.getWorldId(); + const { agentId } = useParams<{ agentId: UUID }>(); + const { data: agentData } = useAgent(agentId); + + const agent = agentData?.data as Agent; + + const toggleDetails = () => setShowDetails(!showDetails); + + console.log(agent); + if (!agentId) return
No data.
; - // Go directly to the chat with the agent, skipping the room selection - return ; + return ( + + + + + + {showDetails && ( + + + + )} + + ); } diff --git a/packages/client/src/routes/home.tsx b/packages/client/src/routes/home.tsx index ece6b0cdd5a..68e4fefe078 100644 --- a/packages/client/src/routes/home.tsx +++ b/packages/client/src/routes/home.tsx @@ -1,17 +1,19 @@ import PageTitle from '@/components/page-title'; import ProfileCard from '@/components/profile-card'; import ProfileOverlay from '@/components/profile-overlay'; -import { Card } from '@/components/ui/card'; -import { useAgents } from '@/hooks/use-query-hooks'; +import { useAgents, useRooms } from '@/hooks/use-query-hooks'; import { formatAgentName } from '@/lib/utils'; +import type { Agent, UUID } from '@elizaos/core'; import { AgentStatus } from '@elizaos/core'; -import type { Agent } from '@elizaos/core'; import { Tooltip, TooltipContent, TooltipTrigger } from '@radix-ui/react-tooltip'; -import { Cog, Info, InfoIcon, Plus } from 'lucide-react'; +import { Cog, InfoIcon, Plus } from 'lucide-react'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useAgentManagement } from '../hooks/use-agent-management'; +import GroupPanel from '@/components/group-panel'; +import { Button } from '../components/ui/button'; +import { Separator } from '../components/ui/separator'; export default function Home() { const { data: { data: agentsData } = {}, isLoading, isError, error } = useAgents(); const navigate = useNavigate(); @@ -19,8 +21,12 @@ export default function Home() { // Extract agents properly from the response const agents = agentsData?.agents || []; + const { data: roomsData } = useRooms(); + const [isOverlayOpen, setOverlayOpen] = useState(false); + const [isGroupPanelOpen, setIsGroupPanelOpen] = useState(false); const [selectedAgent, setSelectedAgent] = useState(null); + const [selectedGroupId, setSelectedGroupId] = useState(null); const { startAgent, isAgentStarting, isAgentStopping } = useAgentManagement(); const openOverlay = (agent: Agent) => { @@ -35,144 +41,225 @@ export default function Home() { return ( <> -
-
- -
+
+
+
+ + +
+ - {isLoading &&
Loading agents...
} + {isLoading &&
Loading agents...
} - {isError && ( -
- Error loading agents: {error instanceof Error ? error.message : 'Unknown error'} -
- )} + {isError && ( +
+ Error loading agents: {error instanceof Error ? error.message : 'Unknown error'} +
+ )} - {agents.length === 0 && !isLoading && ( -
-

- No agents currently running. Start a character to begin. -

-
- )} + {agents.length === 0 && !isLoading && ( +
+

+ No agents currently running. Start a character to begin. +

+
+ )} - {!isLoading && !isError && ( -
- {agents - ?.sort((a: Agent, b: Agent) => Number(b?.enabled) - Number(a?.enabled)) - .map((agent: Agent) => { - return ( - -
{agent.name}
- {agent?.status === AgentStatus.ACTIVE ? ( - - -
- - -

Agent is active

-
- - ) : ( - - -
- - -

Agent is inactive

-
- - )} -
- } - content={ -
openOverlay(agent)} - > + {!isLoading && !isError && ( +
+ {agents + ?.sort((a: Agent, b: Agent) => Number(b?.enabled) - Number(a?.enabled)) + .map((agent: Agent) => { + return ( + +
{agent.name}
+ {agent?.status === AgentStatus.ACTIVE ? ( + + +
+ + +

Agent is active

+
+ + ) : ( + + +
+ + +

Agent is inactive

+
+ + )} +
+ } + content={
openOverlay(agent)} + onKeyUp={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + openOverlay(agent); + } + }} > - {agent.settings?.avatar ? ( - Agent Avatar - ) : ( - formatAgentName(agent.name) +
+ {agent.settings?.avatar ? ( + Agent Avatar + ) : ( + formatAgentName(agent.name) + )} +
+ {agent.status !== AgentStatus.ACTIVE && ( + + Offline + )}
- {agent.status !== AgentStatus.ACTIVE && ( - - Offline - - )} -
- } - buttons={[ - agent.status === AgentStatus.ACTIVE - ? { - label: 'Message', - action: () => navigate(`/chat/${agent.id}`), - className: `w-[80%]`, - variant: 'default', - } - : { - label: isAgentStarting(agent.id) - ? 'Starting...' - : isAgentStopping(agent.id) - ? 'Stopping...' - : 'Start', - action: () => startAgent(agent), - className: `w-[80%]`, - variant: 'default', - disabled: isAgentStarting(agent.id) || isAgentStopping(agent.id), + } + buttons={[ + agent.status === AgentStatus.ACTIVE + ? { + label: 'Message', + action: () => navigate(`/chat/${agent.id}`), + className: 'w-[80%]', + variant: 'default', + } + : { + label: isAgentStarting(agent.id) + ? 'Starting...' + : isAgentStopping(agent.id) + ? 'Stopping...' + : 'Start', + action: () => startAgent(agent), + className: 'w-[80%]', + variant: 'default', + disabled: isAgentStarting(agent.id) || isAgentStopping(agent.id), + }, + { + icon: , + className: 'w-10 h-10 rounded-full', + action: () => { + openOverlay(agent); }, - { - icon: , - className: 'w-10 h-10 rounded-full', - action: () => { - openOverlay(agent); + variant: 'outline', }, - variant: 'outline', - }, - { - icon: , - className: 'w-10 h-10 rounded-full', - action: () => navigate(`/settings/${agent.id}`), - variant: 'outline', - }, - ]} - /> - ); - })} - {/* Create new agent card */} - navigate('/create')} - > -
- - Create New Agent -
-
+ { + icon: , + className: 'w-10 h-10 rounded-full', + action: () => navigate(`/settings/${agent.id}`), + variant: 'outline', + }, + ]} + /> + ); + })} +
+ )} +
+ +
- )} + + + {!isLoading && !isError && ( +
+ {roomsData && + Array.from(roomsData.entries()).map(([roomId, roomArray]) => { + const roomName = roomArray.length > 0 ? roomArray[0]?.name : null; + return ( + +
{roomName}
+
+ } + content={ +
navigate(`/room/${roomId}`)} + onKeyUp={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + navigate(`/room/${roomId}`); + } + }} + > +
+ {formatAgentName(roomName ?? '')} +
+
+ } + buttons={[ + { + label: 'Chat', + action: () => { + navigate(`/room/${roomId}`); + }, + className: 'w-[80%]', + variant: 'default', + }, + { + icon: , + className: 'w-10 h-10 rounded-full', + action: () => { + setSelectedGroupId(roomId as UUID); + setIsGroupPanelOpen(true); + }, + variant: 'outline', + }, + ]} + /> + ); + })} +
+ )} +
+ a.id === selectedAgent?.id) || selectedAgent} + agent={ + agents.find((a) => a.id === selectedAgent?.id) || + (selectedAgent as Agent) || + agents[0] || + ({} as Agent) + } agents={agents} /> + + {isGroupPanelOpen && ( + { + setSelectedGroupId(null); + setIsGroupPanelOpen(false); + }} + groupId={selectedGroupId ?? undefined} + /> + )} ); } diff --git a/packages/client/src/routes/room.tsx b/packages/client/src/routes/room.tsx new file mode 100644 index 00000000000..2e3ba56b724 --- /dev/null +++ b/packages/client/src/routes/room.tsx @@ -0,0 +1,11 @@ +import Room from '@/components/room'; +import type { UUID } from '@elizaos/core'; +import { useParams } from 'react-router'; + +export default function AgentRoute() { + const { serverId } = useParams<{ serverId: UUID }>(); + + if (!serverId) return
No data.
; + + return ; +} diff --git a/packages/core/package.json b/packages/core/package.json index b4947ac6b30..31f75e8537e 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/core", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "description": "", "type": "module", "main": "dist/index.js", @@ -72,5 +72,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55" + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e" } diff --git a/packages/core/src/bootstrap.ts b/packages/core/src/bootstrap.ts index 6586c59cc09..0258f35f11a 100644 --- a/packages/core/src/bootstrap.ts +++ b/packages/core/src/bootstrap.ts @@ -141,7 +141,7 @@ const messageReceivedHandler = async ({ }); // Set up timeout monitoring - const timeoutDuration = 5 * 60 * 1000; // 5 minutes + const timeoutDuration = 60 * 60 * 1000; // 1 hour let timeoutId: NodeJS.Timer; const timeoutPromise = new Promise((_, reject) => { @@ -156,10 +156,10 @@ const messageReceivedHandler = async ({ status: 'timeout', endTime: Date.now(), duration: Date.now() - startTime, - error: 'Run exceeded 5 minute timeout', + error: 'Run exceeded 60 minute timeout', source: 'messageHandler', }); - reject(new Error('Run exceeded 5 minute timeout')); + reject(new Error('Run exceeded 60 minute timeout')); }, timeoutDuration); }); diff --git a/packages/core/src/logger.ts b/packages/core/src/logger.ts index 08ead1708bb..847880022ae 100644 --- a/packages/core/src/logger.ts +++ b/packages/core/src/logger.ts @@ -161,18 +161,58 @@ const raw = parseBooleanFromText(process?.env?.LOG_JSON_FORMAT) || false; const isDebugMode = (process?.env?.LOG_LEVEL || '').toLowerCase() === 'debug'; const effectiveLogLevel = isDebugMode ? 'debug' : process?.env?.DEFAULT_LOG_LEVEL || 'info'; +// Create a function to generate the pretty configuration +const createPrettyConfig = () => ({ + colorize: true, + translateTime: 'yyyy-mm-dd HH:MM:ss', + ignore: 'pid,hostname', + customPrettifiers: { + level: (inputData: any) => { + let level; + if (typeof inputData === 'object' && inputData !== null) { + level = inputData.level || inputData.value; + } else { + level = inputData; + } + + const levelNames: Record = { + 10: 'TRACE', + 20: 'DEBUG', + 27: 'SUCCESS', + 28: 'PROGRESS', + 29: 'LOG', + 30: 'INFO', + 40: 'WARN', + 50: 'ERROR', + 60: 'FATAL', + }; + + if (typeof level === 'number') { + return levelNames[level] || `LEVEL${level}`; + } + + if (level === undefined || level === null) { + return 'UNKNOWN'; + } + + return String(level).toUpperCase(); + }, + // Add a custom prettifier for error messages + msg: (msg: string) => { + // Replace "ERROR (TypeError):" pattern with just "ERROR:" + return msg.replace(/ERROR \([^)]+\):/g, 'ERROR:'); + }, + }, + messageFormat: '{msg}', +}); + const createStream = async () => { if (raw) { return undefined; } // dynamically import pretty to avoid importing it in the browser const pretty = await import('pino-pretty'); - return pretty.default({ - colorize: true, - translateTime: 'yyyy-mm-dd HH:MM:ss', - ignore: 'pid,hostname', - // Don't use minimumLevel since we're filtering in the destination - }); + return pretty.default(createPrettyConfig()); }; // Create options with appropriate level @@ -183,15 +223,33 @@ const options = { logMethod(inputArgs: [string | Record, ...unknown[]], method: LogFn): void { const [arg1, ...rest] = inputArgs; + const formatError = (err: Error) => ({ + message: `(${err.name}) ${err.message}`, + stack: err.stack?.split('\n').map((line) => line.trim()), + }); + if (typeof arg1 === 'object') { - const messageParts = rest.map((arg) => - typeof arg === 'string' ? arg : JSON.stringify(arg) - ); - const message = messageParts.join(' '); - method.apply(this, [arg1, message]); + if (arg1 instanceof Error) { + method.apply(this, [ + { + error: formatError(arg1), + }, + ]); + } else { + const messageParts = rest.map((arg) => + typeof arg === 'string' ? arg : JSON.stringify(arg) + ); + const message = messageParts.join(' '); + method.apply(this, [arg1, message]); + } } else { const context = {}; - const messageParts = [arg1, ...rest].map((arg) => (typeof arg === 'string' ? arg : arg)); + const messageParts = [arg1, ...rest].map((arg) => { + if (arg instanceof Error) { + return formatError(arg); + } + return typeof arg === 'string' ? arg : arg; + }); const message = messageParts.filter((part) => typeof part === 'string').join(' '); const jsonParts = messageParts.filter((part) => typeof part === 'object'); @@ -222,39 +280,7 @@ if (typeof process !== 'undefined') { // This will ensure synchronous loading try { const pretty = require('pino-pretty'); - stream = pretty.default - ? pretty.default({ - colorize: true, - translateTime: 'yyyy-mm-dd HH:MM:ss', - ignore: 'pid,hostname', - customLevels: { - names: { - fatal: 60, - error: 50, - warn: 40, - info: 30, - log: 29, - progress: 28, - success: 27, - debug: 20, - trace: 10, - }, - // Map custom level values to their display text - // This ensures consistent level names in pretty-printed output - customLevelNames: { - 10: 'TRACE', - 20: 'DEBUG', - 27: 'SUCCESS', - 28: 'PROGRESS', - 29: 'LOG', - 30: 'INFO', - 40: 'WARN', - 50: 'ERROR', - 60: 'FATAL', - }, - }, - }) - : null; + stream = pretty.default ? pretty.default(createPrettyConfig()) : null; } catch (e) { // Fall back to async loading if synchronous loading fails createStream().then((prettyStream) => { diff --git a/packages/core/src/providers/recentMessages.ts b/packages/core/src/providers/recentMessages.ts index f66f04ef0b0..419324970e2 100644 --- a/packages/core/src/providers/recentMessages.ts +++ b/packages/core/src/providers/recentMessages.ts @@ -2,6 +2,7 @@ import { getEntityDetails } from '../entities'; import { addHeader, formatMessages, formatPosts } from '../prompts'; import { ChannelType, + CustomMetadata, type Entity, type IAgentRuntime, type Memory, @@ -92,6 +93,12 @@ export const recentMessagesProvider: Provider = { ? addHeader('# Posts in Thread', formattedRecentPosts) : ''; + const metaData = message.metadata as CustomMetadata; + const recieveMessage = addHeader( + '# Received Message:', + `${metaData?.entityName || 'unknown'}: ${message.content.text}` + ); + const recentMessages = formattedRecentMessages && formattedRecentMessages.length > 0 ? addHeader('# Conversation Messages', formattedRecentMessages) @@ -207,7 +214,9 @@ export const recentMessagesProvider: Provider = { }; // Combine all text sections - const text = [isPostFormat ? recentPosts : recentMessages].filter(Boolean).join('\n\n'); + const text = [isPostFormat ? recentPosts : recentMessages + recieveMessage] + .filter(Boolean) + .join('\n\n'); return { data, diff --git a/packages/core/src/roles.ts b/packages/core/src/roles.ts index e6bf7ef68e3..da70674f4bc 100644 --- a/packages/core/src/roles.ts +++ b/packages/core/src/roles.ts @@ -77,6 +77,10 @@ export async function findWorldForOwner( // Find world where the user is the owner for (const world of worlds) { + console.log('world name:', world.name); + console.log('world id:', world.id); + console.log('world agent:', world.agentId); + console.log('world metadata:', world.metadata); if (world.metadata?.ownership?.ownerId === entityId) { return world; } diff --git a/packages/core/src/runtime.ts b/packages/core/src/runtime.ts index 73db21169a1..4263cd63fc2 100644 --- a/packages/core/src/runtime.ts +++ b/packages/core/src/runtime.ts @@ -523,6 +523,7 @@ export class AgentRuntime implements IAgentRuntime { this.runtimeLogger.warn( `[AgentRuntime][${this.character.name}] No TEXT_EMBEDDING model registered. Skipping embedding dimension setup.` ); + console.log('DeBUG models', this.models); } else { // Only run ensureEmbeddingDimension if we have an embedding model await this.ensureEmbeddingDimension(); @@ -1190,7 +1191,7 @@ export class AgentRuntime implements IAgentRuntime { * @returns The room ID of the room between the agent and the user. * @throws An error if the room cannot be created. */ - async ensureRoomExists({ id, name, source, type, channelId, serverId, worldId }: Room) { + async ensureRoomExists({ id, name, source, type, channelId, serverId, worldId, metadata }: Room) { const room = await this.adapter.getRoom(id); if (!room) { await this.adapter.createRoom({ @@ -1202,6 +1203,7 @@ export class AgentRuntime implements IAgentRuntime { channelId, serverId, worldId, + metadata, }); this.runtimeLogger.debug(`Room ${id} created successfully.`); } diff --git a/packages/create-eliza/package.json b/packages/create-eliza/package.json index 3fa5ccf5342..be979a3cb81 100644 --- a/packages/create-eliza/package.json +++ b/packages/create-eliza/package.json @@ -1,6 +1,6 @@ { "name": "create-eliza", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "description": "Initialize an Eliza project", "type": "module", "publishConfig": { @@ -18,7 +18,7 @@ "url": "https://twitter.com/eliza_OS" }, "dependencies": { - "@elizaos/cli": "^1.0.0-beta.2" + "@elizaos/cli": "^1.0.0-beta.7" }, "repository": { "type": "git", @@ -40,7 +40,7 @@ "engines": { "node": ">=14.0.0" }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55", + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e", "devDependencies": { "prettier": "3.5.3" } diff --git a/packages/docs/docs/intro.md b/packages/docs/docs/intro.md index e27834203c7..7de03b0d8c2 100644 --- a/packages/docs/docs/intro.md +++ b/packages/docs/docs/intro.md @@ -128,7 +128,7 @@ cd eliza # Install dependencies and build bun install -bun build +bun run build # Start ElizaOS bun start diff --git a/packages/docs/docusaurus.config.ts b/packages/docs/docusaurus.config.ts index c3b9c879553..fdfce4b222f 100644 --- a/packages/docs/docusaurus.config.ts +++ b/packages/docs/docusaurus.config.ts @@ -8,8 +8,8 @@ const config = { title: 'eliza', tagline: 'Flexible, scalable AI agents for everyone', favicon: 'img/favicon.ico', - url: 'https://elizaos.github.io', - baseUrl: '/eliza/', + url: 'https://eliza.how', + baseUrl: '/', organizationName: 'elizaos', projectName: 'eliza', deploymentBranch: 'gh-pages', @@ -229,7 +229,7 @@ const config = { exclude: ['**/_media/**'], showLastUpdateAuthor: true, showLastUpdateTime: true, - lastVersion: '0.25.9', + lastVersion: 'current', versions: { current: { label: '1.0.0-alpha', @@ -334,11 +334,11 @@ const config = { { label: 'RSS', position: 'left', - to: '/eliza/news', + to: '/news', items: [ - { label: 'RSS (XML)', href: '/eliza/news/rss.xml', target: '_blank' }, - { label: 'Atom', href: '/eliza/news/atom.xml', target: '_blank' }, - { label: 'JSON Feed', href: '/eliza/news/feed.json', target: '_blank' }, + { label: 'RSS (XML)', href: '/news/rss.xml', target: '_blank' }, + { label: 'Atom', href: '/news/atom.xml', target: '_blank' }, + { label: 'JSON Feed', href: '/news/feed.json', target: '_blank' }, ], }, { diff --git a/packages/docs/news/2025-03-12.md b/packages/docs/news/2025-03-12.md new file mode 100644 index 00000000000..21f0e7b4181 --- /dev/null +++ b/packages/docs/news/2025-03-12.md @@ -0,0 +1,60 @@ +# Daily Report – 2025-03-12 + +## Crypto Market Overview + +- **Wrapped Bitcoin (WBTC):** $82,693.37 +- **Wrapped Ethereum (WETH):** $1,921.62 +- **Solana (SOL):** $125.31 +- **ai16z:** $0.1687 + +## AI Agent Development and Governance Updates + +### ElizaOS v2 and AI Agent Enhancements + +- **ElizaOS v2 Beta** launching next week. +- **AI agent 'Degen'** reactivating in main chat and 'arena'. +- **Test channel** for AI agent interactions before full deployment. +- **AI intern agents** evaluated via gamified competition; underperformers may be eliminated. + +### Governance AI Development + +- **Governance AI agent** in development for a Telegram group. +- **Exploring models:** 'Negation Game' governance and 'agency swarm pattern' from RNDao. +- **Discussions on:** AI agent marketplace, tokenomics improvements, and AI-generated content IP concerns. + +## Recent Fixes in ElizaOS + +- **Core type declarations** fix for stability. +- **GUI build and API server** issues resolved. +- **Migration fixes** in version 2 for database consistency. + +## ElizaOS Plugin and Bot Issues + +- **General plugin issues** reported across Twitter, Discord, and Telegram. +- **Twitter plugin fix:** Missing `clients` property resolved. +- **Import error:** `@elizaos-plugins/plugin-example` – verify installation. +- **State persistence issue:** Stored items disappearing; no confirmed fix. +- **Discord bot offline:** Ensure correct `.env` settings and plugin import. +- **Telegram plugin bug:** Duplicate responses; fix by setting `suppressInitialMessage: true`. +- **Twitter plugin fails in Docker;** no solution yet. + +## Implementation of Clean Command in ElizaOS + +- **New 'clean' command** added to core functionality. +- **V2 clean command** proposed with refinements. + +## ElizaOS Updates: Permanent Knowledge Feature and Client App Issues + +- **Permanent knowledge feature** added for AI agents. +- **Client app bug:** Microphone and read-aloud features not working. + +## Recent Discussions and Updates in ElizaOS Community + +- **Topics discussed:** Crypto trading, AI intern competitions, governance AI, and ElizaOS v2 updates. +- **Technical issues:** Plugin failures, bot offline issues, and state persistence problems. +- **ElizaOS v2 Beta:** AI agent 'Degen' to be reactivated. +- **Governance AI agent:** Telegram integration and AI agent marketplace discussions. +- **Unreal Engine 5 (UE5) integration:** Basic operations supported; actions not yet implemented. +- **Merged pull requests:** Core fixes, GUI updates, Docker improvements, and permanent knowledge feature. +- **Bug reports:** Line break formatting issues and client app microphone/play aloud failures. +- **Community contributions:** Six contributors, five pull requests merged. diff --git a/packages/docs/news/2025-03-13.md b/packages/docs/news/2025-03-13.md new file mode 100644 index 00000000000..9003146d50e --- /dev/null +++ b/packages/docs/news/2025-03-13.md @@ -0,0 +1,84 @@ +# Daily Report – 2025-03-13 + +## Cryptocurrency Market Prices Update + +- **Wrapped Bitcoin (WBTC):** $83,502.71 +- **Wrapped Ethereum (WETH):** $1,908.05 +- **Solana (SOL):** $126.59 +- **ai16z:** $0.1758 + +## Client WebSocket Implementation and Chat Analysis + +- **WebSocket PR:** Introduces dedicated socket connections for agents/users. Fixes UI chat memory display issues. + - [GitHub PR #3902](https://github.com/elizaOS/eliza/pull/3902) +- **Chat Analysis:** No meaningful discussions found in transcripts. + +## ElizaOS Development Updates + +- **Token Utility & Governance:** + - Proposed 3D agent marketplace for AI16z token. + - Governance concerns addressed with wrapper contract and proposals forum. +- **Development Progress:** + - V2 release scheduled for Monday. + - Website revamp and mirror.xyz setup in progress. +- **Technical Fixes:** + - Core DTS generation issue resolved. + - [GitHub PR #3898](https://github.com/elizaOS/eliza/pull/3898) +- **Contributions:** + - Six developers contributed, one PR merged. + +## Twitter Plugin Issues and Debugging + +- **Issue:** Plugin fails to start due to missing 'clients' field. + - [GitHub Issue #3901](https://github.com/elizaOS/eliza/issues/3901) +- **Debugging:** + - Investigating `agent/src/index.ts` (line 602). +- **Workaround:** Modify `packages/src/index.ts` to include 'clients' field. + +## AI Trading and Data Enhancements + +### Autonomous Investing & AI Trading + +- **Challenges:** Quantitative trading complexity limits short-term automation. +- **Enhancements:** Sentiment analysis and trading database proposed. +- **Sustainability:** AI agents can generate real profits. +- **Marketing:** Reintroducing Spartan to X (Twitter) suggested. + +### AI News Data Pipeline & Awesome List + +- **Awesome List:** Cleanup and enhancements in progress. +- **News Pipeline:** AI news integration from [madjin.github.io/daily-silk](https://madjin.github.io/daily-silk/). +- **Community Contributions:** Korean translation and newsletter feedback provided. + +## Optimization Improvements in ElizaOS + +- **Cleanup Script Optimization:** + - Improved performance using `xargs -0 rm -rf`. + - [GitHub PR #3900](https://github.com/elizaOS/eliza/pull/3900) +- **SEO Enhancements:** + - Suggested sitemap.xml priority adjustments. + - [GitHub Issue #3904](https://github.com/elizaOS/eliza/issues/3904) + +## Recent Technical Discussions in ElizaOS Community + +- **Governance & Token Utility:** + - 3D agent marketplace proposal. + - DAO governance bottlenecks discussed. +- **Technical Issues & Fixes:** + - Discord message disappearance, Twitter plugin failures, Docker compatibility. +- **Multi-Agent System & Cloud Hosting:** + - Ongoing exploration for ElizaOS. +- **AI News & Sentiment Analysis:** + - New data pipeline integrated. +- **Autonomous Investing & AI Profitability:** + - Feasibility and sustainability discussed. +- **GitHub Updates:** + - Multiple PRs and issues addressed, including WebSocket handling, cleanup script optimization, and SEO improvements. + - [GitHub PRs & Issues](https://github.com/elizaOS/eliza) + +## Summary + +- **Development:** V2 release, governance discussions, and tokenomics updates. +- **Technical Fixes:** WebSocket handling, Twitter plugin debugging, and cleanup script optimization. +- **AI & Trading:** Sentiment analysis, trading database, and AI news pipeline integration. +- **Community Contributions:** Developer engagement, documentation improvements, and marketing strategies. diff --git a/packages/docs/news/2025-03-14.md b/packages/docs/news/2025-03-14.md new file mode 100644 index 00000000000..32739298cea --- /dev/null +++ b/packages/docs/news/2025-03-14.md @@ -0,0 +1,108 @@ +# Daily Report – 2025-03-14 + +## Crypto Market Overview + +- **Wrapped Bitcoin (WBTC):** $80,903.31 +- **Wrapped Ethereum (WETH):** $1,863.39 +- **Solana (SOL):** $123.33 +- **ai16z:** $0.1751 + +## Discord Chat Analysis Summary + +- Chat segments were incomplete or lacked technical discussions. +- Some messages requested the full transcript for proper analysis. +- Mentions of "degenai" and "elizaos v2" with a comment on social engagement. +- No significant problem-solving discussions found. + +## Recent Developments in AI, Web3, and Unreal Engine Integrations + +### Pornhub Partnership Discussion + +- [joaointech] mentioned an introduction to Pornhub founders via an insider. +- Potential partnership could impact project growth. + +### Automated Bot Link Issue + +- [victory.sol] reported a suspended X link associated with a contract address. +- [joaointech] speculated it might be due to data from pump.fun. +- Investigation underway to modify the link. + +### DWTF Staking and Airdrop System + +- **Staking Mechanics:** + - Stake NFT to earn $DWTF. + - Stake $DWTF on GFM to earn $SOL and $DWTF. + - Stake $DWTF on a custom platform for airdrops. +- Phase 1 of the staking platform launched. + +### Green Dough and GFM Ecosystem + +- Green Dough integrates with GFM to detect scams/rugs. +- Jito SOL, Jup, and Meteora partnerships seen as bullish indicators. + +### EztrelaAI Product Evaluation + +- [litn] tested EztrelaAI; functional but not highly refined. +- Speculated market cap growth to 500K. + +### Prometheus Meta and Market Trends + +- Increased interest in Prometheus-related tokens. +- [elvisgan] and [flygod0997] tracked price movements and speculated on growth. + +### Trust Score System + +- Composite trust scores based on a social graph of trusted agents. +- Can be bootstrapped from Eliza trading system trust scores. +- AI16z tokens may be used, favoring agent registry & messaging over NFT-based implementation. + +### Web3 Narrative Marketing Platform + +- Uses Eliza OS Brain to generate and schedule content across platforms (X, LinkedIn, Medium, Farcaster). +- Collects engagement stats and refines content strategy. +- Allows manual editing before posting. + +### Open-Source AI Model Issues + +- Released model lacks text heads, emotional detection, and Gemma-based components. +- TTS is high quality but slow due to inefficient processing. +- Community may optimize for better real-time performance. + +### Humanoid Robotics & Eliza Integration + +- Interest in integrating Eliza AI into humanoid robotics. +- No concrete implementation details yet. + +### Sith Show Runner in Unreal + +- [godfreyart] inquired about running Sith Show Runner in Unreal. +- [smsithlord] suggested using an embedded web browser with a `postMessage` interface. +- Allows Unreal to process events and set cameras while TTS and show playback occur in the web tab. + +### Show Playback Implementation + +- Playback involves stepping through a scene’s dialogue using TTS. +- A sample JSON from a show config and one episode is sufficient to understand the structure. + +### AI-Generated Episodes + +- Any AI, including local Eliza, can generate episodes if the output matches the required JSON format. + +### Eliza Plugin & AI Performance + +- [pendingreality] confirmed the Eliza plugin is available on FAB. +- Primarily interfaces with OpenAI or other APIs. +- Running a local AI model alongside Unreal may cause performance issues. + +## Discord Technical Discussions Summary + +### Agent Chat API Documentation + +- [thanosdasith24] asked about documentation for the agent chat API. +- [dankvr] provided a link to unofficial documentation and mentioned ongoing updates. + +### Debugging Twitter Agent Replies + +- [ordinalwatches] and [boudy__08] discussed ElizaOS agents stopping Twitter replies after a few hours. +- Theorized excessive searches might trigger Twitter rate limits. +- Suggested caching multiple tweets in one pull to reduce API calls. diff --git a/packages/docs/news/2025-03-15.md b/packages/docs/news/2025-03-15.md new file mode 100644 index 00000000000..c646fe4c5f3 --- /dev/null +++ b/packages/docs/news/2025-03-15.md @@ -0,0 +1,121 @@ +# Daily Report - 2025-03-15 + +## Analysis of Discord Chat Transcripts + +- No significant technical discussions or problem-solving identified. +- Minor mentions of technical issues (e.g., `pnpm build` by [shadows.13]) without resolution. +- Messages include unrelated content such as GIFs and general observations. +- No structured analysis, FAQ, or action items generated. + +## Enhancements and Fixes for Autodoc and Documentation in ElizaOS + +### Autodoc Enhancements + +- New feature allows running Autodoc locally with different OpenAI configurations. +- Introduced environment variables: `OPENAI_API_BASE`, `GITHUB_REPOSITORY`, `GITHUB_ACTOR`, `CREATE_BRANCH`. +- Requires further testing; documentation updates pending. +- Test command: `bun run autodoc`. + +### Autodoc Issue Fix + +- `fileUsageDoc` feature was passing only file names, causing AI hallucinations. +- Expected output: multiple use cases and best practices in markdown. + +### Documentation Cleanup + +- Sidebar improvements, video embeds, changelog updates, contributor updates, and RSS link fixes. +- Automated documentation changes now pushed to `autodocs` branch. +- New workflow (`fetch-news.yml`) fetches news updates for RSS. +- `generate-changelog.yml` now pulls content from GitHub releases. + +## Crypto Market Overview + +- **Wrapped Bitcoin (WBTC)**: $83,815.21 +- **Wrapped Ethereum (WETH)**: $1,910.75 +- **Solana (SOL)**: $133.52 +- **ai16z**: $0.1848 + +## Recent Development Updates in ElizaOS + +- **Logging Improvement**: New child logger added for runtime, server, and API routes. +- **Migration Fix**: Unified migration sources to prevent race conditions. +- **General Updates**: + - Fixed Discord plugin error. + - Added avatar initialization from assets folder. + - Three bug fixes. + - Six pull requests merged by five contributors. + +## Technical Issues and V2 Rollout Discussion + +### Twitter Agent Reply Issue + +- **Problem**: Agents stop replying after a while, possibly due to Twitter rate limits. +- **Hypothesis**: Excessive searches may be hitting API limits. +- **Proposed Solution**: Fetch multiple tweets in one request, cache them, and analyze independently. +- **Status**: No confirmed fix; testing ongoing. + +### Twitter Plugin Installation Issue + +- **Problem**: Twitter client stopped working after recent updates. +- **Solution**: + 1. Follow `@sol_nasdaq` on Twitter. + 2. Run: + sh + npx elizaos plugins add @Elizaos-plugins/client-twitter + 3. Update `character.json` to include the plugin. + 4. Run `pnpm build`. + +### Adding PDFs to Agent Knowledge + +- **Solution**: + 1. Use `folder2knowledge` to process PDFs. + 2. Use `knowledge2character` to integrate processed knowledge. + 3. Alternatively, upload PDFs via the Eliza character generator website. + +### DeepSeek Local Model Error + +- **Problem**: Error when running DeepSeek locally with `llama_local` model. +- **Error Message**: `Service text_generation not found`. +- **Status**: No confirmed solution yet. + +### 2FA for Twitter Plugin + +- **Solution**: Use Proton Pass to store OTP codes and manually input them when required. + +### V2 Rollout Discussion + +- **anonfungible** asked about V2 rollout plans. +- **yikesawjeez** suggested AWS Free Tier deployment and plugin development focus. +- **pattatk** proposed an announcement thread with before/after comparisons. +- **yikesawjeez** planned to draft a launch day overview thread. + +### Deployment & Development + +- **new.moon** confirmed running V2 on Replit and as an app. + +## Fixes for Discord Plugin Error and CI Issues + +- **Discord Plugin Fix**: Resolved an error related to the Discord plugin. +- **CI Fixes**: Added missing packages and resolved CI issues. + +## New Features: Avatar Initialization and GUI Thumbnail Upload + +- **Avatar Initialization**: Organization character avatars can now be set from the assets folder. +- **GUI Thumbnail Upload**: New mechanism introduced; removed unused 'enabled' column from the database. + +## ElizaOS Development and Community Discussions + +- **Community Discussions**: + - Solana-based tokens (BORK, LENS, GFM) and their staking, liquidity, and utility. + - Technical issues: Twitter agent failures, plugin installations, AI knowledge integration. +- **V2 Rollout**: + - AWS Free Tier deployment proposal. + - Announcement thread with before/after comparisons. + - Testing deployment on Replit. +- **Development Updates**: + - Fixed Discord plugin error. + - Added avatar initialization feature. + - Implemented GUI thumbnail upload. + - TypeBox integration for type safety. + - Fixed migration race conditions. + - Documentation cleanup. diff --git a/packages/docs/news/2025-03-16.md b/packages/docs/news/2025-03-16.md new file mode 100644 index 00000000000..511bbc91bb0 --- /dev/null +++ b/packages/docs/news/2025-03-16.md @@ -0,0 +1,62 @@ +# Daily Report – 2025-03-16 + +## Chat Analysis and GitHub Pull Request + +- Many chat transcripts lack technical discussions or problem-solving. +- A GitHub pull request: + - Replaces WebSocket Secure (WSS) with Socket.io. + - Switches from Node.js to Bun. + - Ensures `bun run dev` and `bun run build` function correctly. + +## Crypto Market Overview + +- **Wrapped Bitcoin (WBTC):** $84,189.33 +- **Wrapped Ethereum (WETH):** $1,937.77 +- **Solana (SOL):** $135.88 +- **ai16z:** $0.1974 + +## Recent Fixes in ElizaOS + +- Removed an unnecessary parameter to delete memory. +- Fixed: + - Agent's last message animation. + - Profile card display. + - GUI for speech-to-text (STT) and text-to-speech (TTS). + +## Twitter Client Issues and Fixes + +- Users reported issues with Twitter integration in v0.25.9. +- `scraper.getTweetsAndReplies('TwitterDev')` returns an empty object. +- 2FA setup guidance provided using Proton Pass. +- Image generation issues when posting to Twitter remain unresolved. +- Twitter client works with `eliza-starter` but not the main Eliza install. + +## Plugin Documentation and Source Updates + +- Improved SQL plugin documentation (Drizzle). +- Adjusted plugin sources after `plugins.md` relocation. + +## CLI Command Enhancements + +- New CLI command added. +- Improved consistency in CLI command imports. + +## ElizaOS Development and Crypto Discussions + +- **Crypto Discussions:** + - Topics: Green Dough (GFM), YAYDOLF (YE), Lens (LENS), security concerns. + - Action items: Improve tracking for pre-bond tokens, develop scam detection tools. +- **Technical Issues:** + - Errors in DeepSeek, Twitter scrapers, Telegram clients, and ElizaOS plugins. + - Action items: Fix DeepSeek errors, improve Twitter integration, update documentation. +- **Beta Launch Discussion:** + - Linux functional; Windows and Mac have issues. + - Proposed: Warm-up campaign, promo video, collaboration with Sonic’s core team. + - Action items: Fix platform compatibility, update documentation, create marketing materials. +- **GitHub Development:** + - Package manager upgrades, database fixes, logging improvements. + - Added Kluster AI as a model provider. + - GUI fixes, plugin updates, CLI enhancements. +- **GitHub Issues:** + - Twitter client not initializing in main Eliza install. + - Suggested feature: Upload `.env` file via web UI configurator. diff --git a/packages/docs/news/2025-03-17.md b/packages/docs/news/2025-03-17.md new file mode 100644 index 00000000000..46bd451cbb3 --- /dev/null +++ b/packages/docs/news/2025-03-17.md @@ -0,0 +1,87 @@ +# Daily Report – 2025-03-17 + +## Summary of Recent Discussions and Issues + +### Discord Chat Analysis + +- Most analyzed chat transcripts lacked meaningful technical discussions. +- Messages included project promotions, greetings, and minor exchanges. + +### Plugin-Local-AI Fix + +- Removed R1 and added DeepHermes. +- Model downloads now occur only when interacting with the agent. +- Chat and tokenizer functionalities confirmed working. + +### Discord Message Disappearance Issue + +- Messages sent using `callback()` sometimes vanish when sent back-to-back. +- Expected behavior: all messages should remain visible. + +## Fix Missing `await` for Tweet Scraping + +- A missing `await` caused tweet scraping to return a promise instead of data. +- Fix ensures tweets load correctly. + +## ElizaOS Development, Technical Issues, and Future Plans + +### Key Technical Discussions & Solutions + +- **Twitter Client Issue:** Not working in the latest version; manual import suggested. +- **Paradex Plugin Installation Issue:** Missing `@elizaos/core`; solutions include using `npx elizaos plugins add`. +- **WebSocket Support:** Added in Shaw v2 branch but not merged into `develop`. +- **RAG Knowledge Directory Issues:** Errors due to missing directories; solutions include creating directories and setting correct permissions. +- **Llama Model Download Corruption:** Downloads repeatedly; no confirmed fix. + +### ElizaOS V2 Development & Marketing + +- **Beta Release Delay:** Postponed to next Monday. +- **Functionality:** Enhances AI agent communication and customization. +- **Marketing:** Co-marketing with BNB Chain; Binance app displays Binance Alpha Token ($ai16z). +- **Sqd.ai Plugin:** Inquiry about integration; no resolution. + +### Tokenless Project Participation + +- **Integration Questions:** No clear solution; subscription-based access suggested. +- **Monetization:** Fixed subscription fees proposed as an alternative to tokens. +- **Launchpad Mechanics:** No definitive answer on tokenless project participation. + +## Enhancements to Agent Memory and Interaction + +- **Memory Editing Feature:** Users can view and edit agent memories for better recall. +- **User Interaction Scoring:** Conversations are stored and scored to adjust agent behavior. + +## Chore and Feature Updates in Plugin Development + +- **Test Coverage Improvements:** Expanded test cases for `plugin-bootstrap`, improving reliability. +- **Plugin-Local-AI Enhancements:** Memory management improvements and bug fixes. + +## Crypto Market Update + +- **WBTC Price:** $82,423.27 +- **ai16z Price:** $0.1952 + +## ElizaOS Development and Community Discussions + +### Technical Discussions + +- Topics included token trading, AI-managed tokens, and market analytics. +- Discussions on rug pull detection, token prediction models, and analytics terminals. + +### Recent Fixes and Enhancements + +- **Custom Embedding Servers:** Added support. +- **Plugin-Local-AI Fixes:** Improved memory management. +- **Tweet Scraping Fix:** Resolved missing `await`. +- **System Prompt Feature:** Introduced for better agent responses. + +### Reported Issues + +- **Discord Messages Disappearing:** Messages vanish when sent back-to-back. +- **Missing Dependencies:** `opus.node` missing in some installations. +- **Preflight Check CLI Request:** Suggested tool for verifying ElizaOS components. + +### Development Contributions + +- **13 Developers Contributed** +- **Major Work:** Plugin-local-ai improvements, memory management, and test coverage expansion. diff --git a/packages/docs/scripts/fetch-news.sh b/packages/docs/scripts/fetch-news.sh index 9864fa69cbd..18609b095a5 100644 --- a/packages/docs/scripts/fetch-news.sh +++ b/packages/docs/scripts/fetch-news.sh @@ -2,7 +2,7 @@ # Fetch news files for last 10 days into docs/news/ SOURCE_URL="https://m3-org.github.io/ai-news/elizaos/md" -OUTPUT_DIR="docs/news" +OUTPUT_DIR="news" for i in {0..9}; do DATE=$(date -d "-$i days" '+%Y-%m-%d') diff --git a/packages/docs/src/components/DailyNews/index.jsx b/packages/docs/src/components/DailyNews/index.jsx new file mode 100644 index 00000000000..cdbf8f3e485 --- /dev/null +++ b/packages/docs/src/components/DailyNews/index.jsx @@ -0,0 +1,201 @@ +// src/components/DailyNews/index.jsx +import React, { useState, useEffect, useRef } from 'react'; +import clsx from 'clsx'; +import Heading from '@theme/Heading'; +import Link from '@docusaurus/Link'; +import styles from './styles.module.css'; + +export default function DailyNews() { + const [newsData, setNewsData] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [currentDate, setCurrentDate] = useState(''); + const [dateOffset, setDateOffset] = useState(0); + const scrollContainerRef = useRef(null); + + useEffect(() => { + const fetchNews = async () => { + try { + setLoading(true); + + // Calculate the date based on current offset + const targetDate = new Date(); + targetDate.setDate(targetDate.getDate() - dateOffset); + const dateStr = targetDate.toISOString().split('T')[0]; + + // If dateOffset is 0, try to fetch the latest news first + let response; + if (dateOffset === 0) { + response = await fetch('https://m3-org.github.io/ai-news/elizaos/json/daily.json'); + } + + // If we need a specific date or daily isn't available + if (dateOffset > 0 || !response || !response.ok) { + response = await fetch(`https://m3-org.github.io/ai-news/elizaos/json/${dateStr}.json`); + if (!response.ok) { + throw new Error(`No news available for ${dateStr}`); + } + } + + const data = await response.json(); + setNewsData(data); + setCurrentDate(dateStr); + } catch (err) { + console.error('Error fetching news:', err); + setError(err.message || 'Failed to load news updates.'); + } finally { + setLoading(false); + } + }; + + fetchNews(); + }, [dateOffset]); + + // Format the date for display + const formatDate = (dateString) => { + const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; + return new Date(dateString).toLocaleDateString(undefined, options); + }; + + // Next day handler (go back in time) + const handlePrevDay = () => { + setDateOffset((prev) => prev + 1); + }; + + // Previous day handler (go forward in time) + const handleNextDay = () => { + if (dateOffset > 0) { + setDateOffset((prev) => prev - 1); + } + }; + + // Scroll handlers + const handleScrollLeft = () => { + if (scrollContainerRef.current) { + scrollContainerRef.current.scrollBy({ left: -300, behavior: 'smooth' }); + } + }; + + const handleScrollRight = () => { + if (scrollContainerRef.current) { + scrollContainerRef.current.scrollBy({ left: 300, behavior: 'smooth' }); + } + }; + + // Get flattened news items from all categories + const getAllNewsItems = () => { + if (!newsData || !newsData.categories) return []; + + return newsData.categories + .flatMap((category) => + category.content.map((item) => ({ + ...item, + category: category.title, + topic: category.topic, + })) + ) + .slice(0, 12); // Limit to 12 items total + }; + + return ( +
+
+
+ + News + + +
+ + +
+ {currentDate && {formatDate(currentDate)}} +
+ + +
+ + + View All + +
+ + {loading ? ( +
+
+

Loading updates...

+
+ ) : error ? ( +
+

{error}

+
+ ) : ( +
+ + +
+ {getAllNewsItems().map((item, idx) => ( +
+ {item.topic && {item.topic}} +

{item.category}

+ +
+

{item.text}

+
+
+ + {item.sources && item.sources.length > 0 && ( +
+ {item.sources.slice(0, 1).map((source, sourceIdx) => + source.startsWith('http') ? ( + + Source + + ) : null + )} + {item.sources.length > 1 && ( + +{item.sources.length - 1} + )} +
+ )} +
+ ))} +
+ + +
+ )} +
+
+ ); +} diff --git a/packages/docs/src/components/DailyNews/styles.module.css b/packages/docs/src/components/DailyNews/styles.module.css new file mode 100644 index 00000000000..f36abd5a618 --- /dev/null +++ b/packages/docs/src/components/DailyNews/styles.module.css @@ -0,0 +1,314 @@ +/* src/components/DailyNews/styles.module.css */ +.newsSection { + padding: 2rem 0; + background: var(--ifm-background-surface-color); + position: relative; +} + +.newsHeader { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 1.5rem; + margin-bottom: 1.5rem; + flex-wrap: wrap; + gap: 1rem; +} + +.newsTitle { + font-size: 1.4rem; + margin: 0; + flex-shrink: 0; +} + +.dateNavigation { + display: flex; + align-items: center; + margin-left: 3rem; + display: flex; + background: var(--ifm-card-background-color); + border-radius: 50px; + padding: 0.3rem; + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.dateDisplay { + font-size: 0.9rem; + font-weight: 500; + padding: 0 0.8rem; + white-space: nowrap; +} + +.dateButton { + background: none; + border: none; + border-radius: 50%; + width: 30px; + height: 30px; + font-size: 1.2rem; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + color: var(--ifm-font-color-base); +} + +.dateButton:hover:not(:disabled) { + background: rgba(255, 166, 0, 0.1); + color: var(--ifm-color-primary); +} + +.dateButton:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.viewAllButton { + font-size: 0.9rem; + padding: 0.25rem 0.8rem; + height: 32px; + margin-left: auto; +} + +.carouselContainer { + position: relative; + margin: 0 -1rem; +} + +.scrollButton { + position: absolute; + top: 50%; + transform: translateY(-50%); + z-index: 10; + background: var(--ifm-card-background-color); + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 50%; + width: 40px; + height: 40px; + font-size: 1.5rem; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + transition: all 0.2s ease; + color: var(--ifm-font-color-base); +} + +.scrollButton:hover { + background: var(--ifm-color-primary); + color: white; +} + +.scrollButtonLeft { + left: 0.5rem; +} + +.scrollButtonRight { + right: 0.5rem; +} + +.newsCarousel { + display: flex; + overflow-x: auto; + scroll-behavior: smooth; + -ms-overflow-style: none; /* Hide scrollbar for IE and Edge */ + scrollbar-width: none; /* Hide scrollbar for Firefox */ + padding: 0.5rem 2.5rem; + gap: 1rem; +} + +.newsCarousel::-webkit-scrollbar { + display: none; /* Hide scrollbar for Chrome, Safari and Opera */ +} + +.newsCard { + flex: 0 0 400px; + background: var(--ifm-card-background-color); + border-radius: 8px; + border: 1px solid rgba(255, 255, 255, 0.1); + padding: 1rem; + height: 240px; + display: flex; + flex-direction: column; + position: relative; + transition: all 0.3s ease; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); +} + +.newsCard:hover { + transform: translateY(-4px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12); + border-color: var(--ifm-color-primary-lighter); +} + +.topicBadge { + position: absolute; + bottom: 1rem; + right: 1rem; + background: rgba(255, 166, 0, 0.15); + color: var(--ifm-color-primary); + font-size: 0.7rem; + font-weight: 500; + padding: 0.2rem 0.6rem; + border-radius: 10px; +} + +.itemCategory { + font-size: 1rem; + margin: 0 0 0.8rem; +} + +.newsContent { + position: relative; + flex: 1; + overflow: hidden; +} + +.newsText { + margin: 0; + font-size: 0.9rem; + line-height: 1.4; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 6; + -webkit-box-orient: vertical; +} + +.textFade { + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 40px; + background: linear-gradient( + to bottom, + rgba(255, 255, 255, 0) 0%, + var(--ifm-card-background-color) 90% + ); + pointer-events: none; +} + +[data-theme='dark'] .textFade { + background: linear-gradient( + to bottom, + rgba(30, 41, 59, 0) 0%, + var(--ifm-card-background-color) 90% + ); +} + +.sourceLinks { + margin-top: 0.8rem; + font-size: 0.8rem; + display: flex; + gap: 0.5rem; + align-items: center; +} + +.sourceLink { + color: var(--ifm-color-primary); + display: inline-flex; + align-items: center; + font-weight: 500; +} + +.moreSources { + opacity: 0.7; + font-size: 0.75rem; +} + +.loadingContainer, +.errorContainer { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 120px; + padding: 1rem; +} + +.loadingSpinner { + width: 30px; + height: 30px; + border: 3px solid rgba(255, 166, 0, 0.1); + border-radius: 50%; + border-top-color: var(--ifm-color-primary); + animation: spin 1s linear infinite; + margin-bottom: 0.8rem; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +/* Media Queries for Responsiveness */ +@media (max-width: 996px) { + .newsHeader { + flex-wrap: wrap; + } + + .dateNavigation { + order: 2; + } + + .viewAllButton { + order: 1; + } + + .newsTitle { + width: 100%; + order: 0; + } +} + +@media (max-width: 768px) { + .scrollButton { + width: 36px; + height: 36px; + font-size: 1.2rem; + } + + .newsCard { + flex: 0 0 260px; + height: 220px; + } + + .newsText { + -webkit-line-clamp: 5; + } +} + +@media (max-width: 576px) { + .newsCard { + flex: 0 0 220px; + height: 200px; + } + + .newsText { + -webkit-line-clamp: 4; + font-size: 0.85rem; + } + + .itemCategory { + font-size: 0.95rem; + } + + .carouselContainer { + margin: 0 -0.5rem; + } + + .newsCarousel { + padding: 0.5rem 2rem; + } + + .scrollButtonLeft { + left: 0.2rem; + } + + .scrollButtonRight { + right: 0.2rem; + } +} diff --git a/packages/docs/src/components/HomepageFeatures/index.jsx b/packages/docs/src/components/HomepageFeatures/index.jsx index b6de641edd0..9d9b1eb5b16 100644 --- a/packages/docs/src/components/HomepageFeatures/index.jsx +++ b/packages/docs/src/components/HomepageFeatures/index.jsx @@ -1,6 +1,8 @@ +// src/components/HomepageFeatures/index.jsx import React from 'react'; import clsx from 'clsx'; import Heading from '@theme/Heading'; +import Link from '@docusaurus/Link'; import styles from './styles.module.css'; const FeatureList = [ @@ -10,19 +12,21 @@ const FeatureList = [ description: ( <> Build and deploy autonomous AI agents with consistent personalities across - Discord, Twitter, and Telegram. Full support for voice, text, and media interactions. + platforms. Full support for voice, text, and media interactions. ), + link: '/docs/core/agents', }, { icon: '🧠', - title: 'Advanced Capabilities', + title: 'Knowledge Management', description: ( <> - Built-in RAG memory system, document processing, media analysis, and autonomous trading - capabilities. Supports multiple AI models including Llama, GPT-4, and Claude. + Powerful RAG system with document processing and semantic search. Import PDFs, markdown, and + text files to build comprehensive knowledge bases. ), + link: '/docs/core/knowledge', }, { icon: '🔌', @@ -33,46 +37,268 @@ const FeatureList = [ modular plugin system. Full TypeScript support. ), + link: '/docs/core/plugins', + }, + { + icon: '💭', + title: 'Self-Reflection', + description: ( + <> + Agents learn from interactions through built-in reflection mechanisms that extract facts, + build relationships, and improve responses over time. + + ), + link: '/docs/core/reflection', + }, + { + icon: '💬', + title: 'Platform Integrations', + description: ( + <> + Connect seamlessly with Discord, Twitter, Telegram, Slack, Farcaster, and more through + standardized service abstractions. + + ), + link: '/docs/core/services', + }, + { + icon: '🌐', + title: 'Worlds & Rooms', + description: ( + <> + Organize interactions with flexible world and room structures. Create multi-agent + environments with defined relationships and contexts. + + ), + link: '/docs/core/worlds', + }, + { + icon: '⚡', + title: 'Action System', + description: ( + <> + Define agent capabilities with the actions system. From simple replies to complex + interactions like blockchain transactions or content generation. + + ), + link: '/docs/core/actions', + }, + { + icon: '📅', + title: 'Task Management', + description: ( + <> + Schedule activities, implement reminders, and create multi-step workflows with the built-in + task system for deferred and recurring operations. + + ), + link: '/docs/core/tasks', + }, + { + icon: '👤', + title: 'Entity-Component Architecture', + description: ( + <> + Flexible data modeling with entities, components, and relationships. Build rich + representations of users, objects, and their connections. + + ), + link: '/docs/core/entities', + }, +]; + +const QuickActionsList = [ + { + image: '/img/eliza_banner.jpg', + title: 'Create an Agent', + description: ( + <> + Get started building your first autonomous AI agent with our step-by-step + quickstart. + + + ), + link: '/docs/quickstart', + }, + { + image: '/img/montage-plugins.jpg', + title: 'Discover Plugins', + description: ( + <> + Explore the ecosystem of plugins that extend your agent's abilities and integrations across + platforms. + + ), + link: '/packages', + }, + { + image: '/img/banner2.png', + title: 'Get Inspired', + description: ( + <> + Browse examples and resources from the community to spark ideas for your next AI agent + project. + + ), + link: '/docs/intro', }, ]; -function Feature({ icon, title, description }) { +const UseCases = [ + { + title: 'Social Media Personas', + description: + 'Create autonomous agents that post content, respond to mentions, and engage with followers', + icon: '💬', + }, + { + title: 'Community Managers', + description: 'Build AI moderators that enforce rules, answer questions, and foster engagement', + icon: '👥', + }, + { + title: 'Autonomous Traders', + description: 'Deploy agents that monitor markets, execute trades, and manage portfolios', + icon: '📈', + }, + { + title: 'Content Creation', + description: 'Generate blog posts, newsletters, and social content with consistent voice', + icon: '✍️', + }, +]; + +function Feature({ icon, title, description, link, image }) { + return ( +
+
+ {image ? ( + {title} + ) : ( +
{icon}
+ )} +
+
+ + {title} + +
{description}
+ {link && ( + + Learn more + + )} +
+
+ ); +} + +function ClickableFeature({ icon, title, description, link, image }) { return ( -
-
-
- {icon} - + +
+
+ {image ? ( + {title} + ) : ( +
{icon}
+ )} +
+
+ {title} -

{description}

+
{description}
+ + ); +} + +function UseCase({ title, description, icon }) { + return ( +
+
{icon}
+
+

{title}

+

{description}

+
); } -export default function HomepageFeatures() { +export default function HomepageFeatures({ type = 'features', showUseCases = true }) { + const renderFeatures = () => ( + <> +
+ + Core Features + +

+ Everything you need to build powerful AI agents with personality and purpose +

+
+ +
+ {FeatureList.map((props, idx) => ( + + ))} +
+ + {showUseCases && ( + <> +
+ +
+ + Use Cases + +

Versatile applications across various domains

+
+ +
+ {UseCases.map((useCase, idx) => ( + + ))} +
+ +
+ + Get Started with Eliza + + + Join our Community + +
+ + )} + + ); + + const renderQuickActions = () => ( + <> +
+ + Quick Actions + +

Everything you need to get started with elizaOS

+
+
+ {QuickActionsList.map((props, idx) => ( + + ))} +
+ + ); + return (
-
-
- {FeatureList.map((props, idx) => ( - - ))} -
-
+ {type === 'quickactions' ? renderQuickActions() : renderFeatures()}
); diff --git a/packages/docs/src/components/HomepageFeatures/styles.module.css b/packages/docs/src/components/HomepageFeatures/styles.module.css index 8c7ff50f7fe..2f1369537c5 100644 --- a/packages/docs/src/components/HomepageFeatures/styles.module.css +++ b/packages/docs/src/components/HomepageFeatures/styles.module.css @@ -1,59 +1,310 @@ +/* src/components/HomepageFeatures/styles.module.css */ .features { - display: flex; - align-items: center; - padding: 2rem 0; + padding: 4rem 0; width: 100%; - flex-wrap: wrap; } -.featureSvg { - height: 200px; - width: 200px; +.sectionHeader { + text-align: center; + margin-bottom: 3rem; } -.featureIcon { - height: 100px; - width: 100px; - font-size: 2rem; +.sectionTitle { + font-size: 2.5rem; + margin-bottom: 1rem; + font-weight: 700; +} + +.sectionSubtitle { + font-size: 1.2rem; + opacity: 0.8; + max-width: 700px; + margin: 0 auto; } .featureGrid { display: grid; grid-template-columns: repeat(3, 1fr); + gap: 2rem; + margin-bottom: 4rem; +} + +.featureCard { + background: var(--ifm-card-background-color); + border-radius: 12px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); + overflow: hidden; + transition: all 0.3s ease; + height: 100%; + display: flex; + flex-direction: column; + border: 1px solid rgba(255, 255, 255, 0.08); + position: relative; +} + +.featureCard:hover { + transform: translateY(-8px); + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.12); + border-color: var(--ifm-color-primary-lighter); +} + +.featureIconWrapper { + padding: 1.5rem 1.5rem 0; +} + +.featureIcon { + font-size: 2.5rem; + line-height: 1; + margin-bottom: 1rem; + background: rgba(255, 166, 0, 0.1); + width: 60px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 12px; +} + +.featureContent { + padding: 1.5rem; + flex: 1; + display: flex; + flex-direction: column; +} + +.featureTitle { + font-size: 1.4rem; + margin-bottom: 1rem; + font-weight: 600; +} + +.featureDescription { + margin-bottom: 1.5rem; + line-height: 1.6; + font-size: 0.95rem; + flex: 1; +} + +.featureLink { + display: inline-flex; + align-items: center; + color: var(--ifm-color-primary); + font-weight: 500; + text-decoration: none; + transition: all 0.2s ease; + font-size: 0.95rem; + margin-top: auto; + position: relative; + padding-bottom: 0.25rem; +} + +.featureLink:after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 0; + height: 2px; + background-color: var(--ifm-color-primary); + transition: width 0.3s ease; +} + +.featureLink:hover:after { + width: 100%; +} + +.featureLink:hover { + color: var(--ifm-color-primary-darker); + text-decoration: none; +} + +.arrowIcon { + transition: transform 0.2s ease; + margin-left: 5px; +} + +.featureLink:hover .arrowIcon { + transform: translateX(4px); +} + +.sectionDivider { + height: 1px; + background: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0%, + rgba(255, 255, 255, 0.1) 50%, + rgba(255, 255, 255, 0) 100% + ); + margin: 2rem 0 4rem; +} + +.useCaseGrid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 2rem; + margin-bottom: 4rem; +} + +.useCaseItem { + background: var(--ifm-background-surface-color); + border-radius: 10px; + padding: 1.5rem; + display: flex; + align-items: flex-start; gap: 1rem; + transition: all 0.3s ease; + border: 1px solid rgba(255, 255, 255, 0.05); } -@media (max-width: 768px) { +.useCaseItem:hover { + transform: translateY(-5px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); + border-color: var(--ifm-color-primary-lighter); + background: var(--ifm-card-background-color); +} + +.useCaseIcon { + font-size: 1.8rem; + background: rgba(255, 166, 0, 0.1); + width: 50px; + height: 50px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 12px; + flex-shrink: 0; +} + +.useCaseTitle { + font-size: 1.2rem; + margin: 0 0 0.8rem; + font-weight: 600; +} + +.useCaseDescription { + margin: 0; + font-size: 0.95rem; + opacity: 0.9; + line-height: 1.5; +} + +.actionSection { + text-align: center; + margin-top: 3rem; + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; +} + +.communityLink { + display: inline-flex; + align-items: center; + color: var(--ifm-color-primary); + font-weight: 500; + text-decoration: none; + transition: all 0.2s ease; + font-size: 1rem; + margin-top: 1rem; +} + +.communityLink:hover { + color: var(--ifm-color-primary-darker); + text-decoration: none; +} + +.communityLink:hover .arrowIcon { + transform: translateX(4px); +} + +.cardLink { + text-decoration: none; + color: inherit; + display: block; + height: 100%; +} + +.cardLink:hover { + text-decoration: none; + color: inherit; +} + +/* Add support for feature images */ +.featureImage { + width: 100%; + height: 200px; + object-fit: cover; + transition: transform 0.5s ease; +} + +.featureCard:hover .featureImage { + transform: scale(1.05); +} + +.secondaryLinks { + margin-top: 1rem; + font-size: 0.9rem; +} + +.secondaryLink { + display: inline-flex; + align-items: center; + color: var(--ifm-color-emphasis-700); + text-decoration: none; + transition: color 0.2s; + margin-right: 1rem; +} + +.secondaryLink:hover { + color: var(--ifm-color-primary); + text-decoration: none; +} + +.secondaryLinkIcon { + margin-right: 0.4rem; + font-size: 1rem; +} + +/* Media Queries for Responsiveness */ +@media (max-width: 996px) { .featureGrid { grid-template-columns: repeat(2, 1fr); - gap: 0rem; } - .featureSvg { - height: 150px; - width: 150px; + .sectionTitle { + font-size: 2.2rem; + } +} + +@media (max-width: 768px) { + .features { + padding: 3rem 0; + } + + .useCaseGrid { + grid-template-columns: 1fr; } - .featureIcon { - height: 80px; - width: 80px; - font-size: 1.5rem; + .sectionTitle { + font-size: 2rem; } } -@media (max-width: 480px) { +@media (max-width: 576px) { .featureGrid { grid-template-columns: 1fr; } - .featureSvg { - height: 100px; - width: 100px; + .sectionTitle { + font-size: 1.8rem; + } + + .useCaseItem { + flex-direction: column; + align-items: flex-start; } - .featureIcon { - height: 60px; - width: 60px; - font-size: 1.2rem; + .useCaseIcon { + margin-bottom: 1rem; } } diff --git a/packages/docs/src/components/HomepageHeader/index.jsx b/packages/docs/src/components/HomepageHeader/index.jsx index 7feef8ca448..092222a5b7e 100644 --- a/packages/docs/src/components/HomepageHeader/index.jsx +++ b/packages/docs/src/components/HomepageHeader/index.jsx @@ -1,5 +1,7 @@ +// src/components/HomepageHeader/index.jsx import React from 'react'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import Link from '@docusaurus/Link'; import Heading from '@theme/Heading'; import styles from './styles.module.css'; @@ -10,33 +12,60 @@ function HomepageHeader() {
-
+

- A framework for
- capable AI agents + eliza is a{' '} + powerful AI agent framework for + autonomy & personality

{siteConfig.tagline}

- + Get Started - +
+

+ NEW! Copy{' '} + + llms.txt + {' '} + to chat with the docs using LLMs +

- blurred -
-              {`npm install @elizaos/core`}
-            
+
+
+
+
+
+
+
+
terminal
+
+
+                  
+                    # Create your first AI agent
+                    
+ $ npm create eliza@beta +
+ ✓ Project initialized successfully! +
+ $ cd my-agent && npm run start +
+
+
+
+
diff --git a/packages/docs/src/components/HomepageHeader/styles.module.css b/packages/docs/src/components/HomepageHeader/styles.module.css index f134303c6ab..e576a972ffe 100644 --- a/packages/docs/src/components/HomepageHeader/styles.module.css +++ b/packages/docs/src/components/HomepageHeader/styles.module.css @@ -1,132 +1,332 @@ +/* src/components/HomepageHeader/styles.module.css */ +.heroBanner { + padding: 5rem 0 0; + position: relative; + overflow: visible; +} + +.heroSection { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 2rem; + position: relative; + padding-bottom: 2rem; +} + +.heroLeft { + display: flex; + flex-direction: column; + justify-content: center; + z-index: 1; +} + .heroTitle { font-size: 3.2rem; - font-weight: 700; - margin-bottom: 1rem; - line-height: 1.4; + font-weight: 800; + line-height: 1.2; + margin-bottom: 1.5rem; + letter-spacing: -0.02em; } -.heroSubtitle { - font-size: 1.5rem; - opacity: 0.8; +.heroTitlePrefix { + font-weight: 900; + letter-spacing: -0.03em; } -.heroSection { - padding: 6rem 2rem 0rem; - display: grid; - grid-template-columns: 1fr 1fr; - margin: 0 auto; - max-width: 100%; +.heroTitleHighlight { + background: linear-gradient(135deg, var(--ifm-color-primary) 0%, #ff7700 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + text-fill-color: transparent; + font-weight: 800; } -.reg-button { - background-color: pink; +.heroSubtitle { + font-size: 1.5rem; + opacity: 0.8; + margin-bottom: 2rem; + line-height: 1.4; } .buttonGroup { display: flex; + align-items: center; gap: 1rem; + flex-wrap: wrap; +} + +.secondaryButton { + display: inline-flex; + align-items: center; + padding: 0.8rem 1.5rem; + font-size: 1rem; + font-weight: 500; + background: transparent; + color: var(--ifm-color-primary); + border: 2px solid var(--ifm-color-primary); + border-radius: 8px; + transition: all 0.3s ease; +} + +.secondaryButton:hover { + background: rgba(255, 166, 0, 0.1); + text-decoration: none; } .githubButton { - margin-top: 1rem; + display: flex; + align-items: center; + margin-left: 0.5rem; } +/* Right side styling */ .heroRight { display: flex; - flex-direction: column; - justify-content: center; align-items: center; + justify-content: center; position: relative; } -.codeBlock { +.heroVisual { + position: relative; + width: 100%; + height: 100%; + min-height: 400px; display: flex; - background: #242736; - color: white; - padding-left: 1.5rem; - padding-right: 1.5rem; + align-items: center; + justify-content: center; +} + +.blurCircle { + position: absolute; + width: 350px; + height: 350px; + background: radial-gradient(circle, rgba(255, 166, 0, 0.2) 0%, rgba(255, 166, 0, 0) 70%); + border-radius: 50%; + filter: blur(40px); + opacity: 0.6; + z-index: 0; +} + +[data-theme='dark'] .blurCircle { + background: radial-gradient( + circle, + rgba(255, 149, 0, 0.25) 0%, + rgba(255, 98, 0, 0.1) 50%, + rgba(255, 98, 0, 0) 70% + ); + opacity: 0.8; +} + +.codeBlockWrapper { position: relative; + width: 100%; + max-width: 500px; + background: #1a1a1a; + border-radius: 12px; + box-shadow: + 0 20px 40px rgba(0, 0, 0, 0.2), + 0 0 0 1px rgba(255, 255, 255, 0.1); + overflow: hidden; z-index: 1; - opacity: 0.9; + transform: perspective(1000px) rotateY(-5deg) rotateX(2deg); + transition: all 0.3s ease; } -.headerTextGradient { - background: linear-gradient(180deg, #ffa600 0%, #ff6f00 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; +.codeBlockWrapper:hover { + transform: perspective(1000px) rotateY(-2deg) rotateX(1deg) translateY(-5px); + box-shadow: + 0 25px 50px rgba(0, 0, 0, 0.25), + 0 0 0 1px rgba(255, 255, 255, 0.15); +} + +.codeBlockHeader { + background: #252525; + padding: 0.8rem 1rem; + display: flex; + align-items: center; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.codeBlockDot { + width: 12px; + height: 12px; + border-radius: 50%; + margin-right: 8px; +} + +.codeBlockDot:nth-child(1) { + background: #ff5f57; +} + +.codeBlockDot:nth-child(2) { + background: #febc2e; +} + +.codeBlockDot:nth-child(3) { + background: #28c840; } -.blurPhoto { - filter: blur(15px); - border-radius: 45%; +.codeFileName { + margin-left: 1rem; + color: rgba(255, 255, 255, 0.6); + font-size: 0.85rem; + font-family: monospace; +} + +.codeBlock { + background: #0a0a0a; + color: #f8f8f8; + padding: 1.5rem; + font-family: monospace; + font-size: 1rem; + line-height: 1.6; + overflow-x: auto; + white-space: pre; + margin: 0; + border-radius: 0; +} + +.prompt { + color: #7b9aff; + font-weight: bold; + margin-right: 0.5rem; +} + +.comment { + color: #6a737d; +} + +.successText { + color: #28c840; +} + +.floatingFeatures { position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); + top: 0; + right: 0; + display: flex; + flex-direction: column; + gap: 1rem; + transform: translateX(40px); + z-index: 0; +} + +.featureBadge { + background: var(--ifm-background-surface-color); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + border-radius: 50px; + padding: 0.6rem 1rem; + font-size: 0.9rem; + font-weight: 500; + display: flex; + align-items: center; + gap: 0.5rem; + transition: all 0.3s ease; + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.featureBadge:hover { + transform: translateX(-5px); + box-shadow: 0 6px 25px rgba(0, 0, 0, 0.2); + border-color: var(--ifm-color-primary-lighter); +} + +.featureBadge span { + font-size: 1.2rem; +} + +@keyframes float { + 0% { + transform: translateY(0px); + } + 50% { + transform: translateY(-10px); + } + 100% { + transform: translateY(0px); + } +} + +.featureBadge:nth-child(1) { + animation: float 6s ease-in-out infinite; +} + +.featureBadge:nth-child(2) { + animation: float 7s ease-in-out infinite; + animation-delay: 1s; +} + +.featureBadge:nth-child(3) { + animation: float 8s ease-in-out infinite; + animation-delay: 2s; } /* Media Queries for Responsiveness */ -@media (max-width: 1024px) { +@media (max-width: 996px) { .heroSection { grid-template-columns: 1fr; - padding: 4rem 1rem 0rem; text-align: center; - gap: 2rem; + gap: 3rem; + } + + .heroTitle { + font-size: 2.8rem; } .buttonGroup { justify-content: center; - position: relative; - z-index: 1; } - .heroTitle { - font-size: 3rem; + .heroVisual { + min-height: 300px; } - .heroSubtitle { - font-size: 1.3rem; + .floatingFeatures { + display: none; + } + + .codeBlockWrapper { + transform: none; + max-width: 600px; + } + + .codeBlockWrapper:hover { + transform: translateY(-5px); } } @media (max-width: 768px) { - .heroSection { - padding: 3rem 1rem 0rem; + .heroBanner { + padding: 3rem 0 0; } .heroTitle { - font-size: 2rem; + font-size: 2.2rem; } .heroSubtitle { - font-size: 1rem; - } - - .codeBlock { - padding-left: 1rem; - padding-right: 1rem; + font-size: 1.2rem; } } -@media (max-width: 480px) { - .heroSection { - padding: 2rem 1rem 0rem; - } - +@media (max-width: 576px) { .heroTitle { - font-size: 1.5rem; + font-size: 1.8rem; } .heroSubtitle { - font-size: 0.9rem; + font-size: 1rem; } .buttonGroup { flex-direction: column; - gap: 0.5rem; + align-items: stretch; } .githubButton { - margin-top: 0.5rem; + margin: 1rem 0 0; + justify-content: center; } } diff --git a/packages/docs/src/data/registry-users.tsx b/packages/docs/src/data/registry-users.tsx index bfac883e566..da0af7f191a 100644 --- a/packages/docs/src/data/registry-users.tsx +++ b/packages/docs/src/data/registry-users.tsx @@ -5,7 +5,7 @@ export const registryUsers: User[] = [ { title: 'Mongodb', description: 'Database adapter for MongoDB enabling document storage with query capabilities.', - preview: '/eliza/logos/mongodb.png', + preview: '/logos/mongodb.png', website: 'https://github.com/elizaos-plugins/adapter-mongodb', source: 'https://github.com/elizaos-plugins/adapter-mongodb', tags: ['adapter'], @@ -13,7 +13,7 @@ export const registryUsers: User[] = [ { title: 'Postgres', description: 'Database adapter for PostgreSQL with full relational database capabilities.', - preview: '/eliza/logos/postgres.jpg', + preview: '/logos/postgres.jpg', website: 'https://github.com/elizaos-plugins/adapter-postgres', source: 'https://github.com/elizaos-plugins/adapter-postgres', tags: ['adapter'], @@ -21,7 +21,7 @@ export const registryUsers: User[] = [ { title: 'Pglite', description: 'Lightweight PostgreSQL adapter for embedded database applications.', - preview: '/eliza/logos/pglite.png', + preview: '/logos/pglite.png', website: 'https://github.com/elizaos-plugins/adapter-pglite', source: 'https://github.com/elizaos-plugins/adapter-pglite', tags: ['adapter'], @@ -29,7 +29,7 @@ export const registryUsers: User[] = [ { title: 'Qdrant', description: 'Vector database adapter for Qdrant with similarity search capabilities.', - preview: '/eliza/logos/qdrant.png', + preview: '/logos/qdrant.png', website: 'https://github.com/elizaos-plugins/adapter-qdrant', source: 'https://github.com/elizaos-plugins/adapter-qdrant', tags: ['adapter'], @@ -37,7 +37,7 @@ export const registryUsers: User[] = [ { title: 'Sqljs', description: 'In-memory SQL database adapter for browser-based applications.', - preview: '/eliza/logos/sqljs.png', + preview: '/logos/sqljs.png', website: 'https://github.com/elizaos-plugins/adapter-sqljs', source: 'https://github.com/elizaos-plugins/adapter-sqljs', tags: ['adapter'], @@ -45,7 +45,7 @@ export const registryUsers: User[] = [ { title: 'Sqlite', description: 'File-based SQL database adapter for lightweight local storage.', - preview: '/eliza/logos/sqlite.png', + preview: '/logos/sqlite.png', website: 'https://github.com/elizaos-plugins/adapter-sqlite', source: 'https://github.com/elizaos-plugins/adapter-sqlite', tags: ['adapter'], @@ -53,7 +53,7 @@ export const registryUsers: User[] = [ { title: 'Supabase', description: 'Database adapter for Supabase with PostgreSQL and realtime capabilities.', - preview: '/eliza/logos/supabase.jpg', + preview: '/logos/supabase.jpg', website: 'https://github.com/elizaos-plugins/adapter-supabase', source: 'https://github.com/elizaos-plugins/adapter-supabase', tags: ['adapter'], @@ -61,7 +61,7 @@ export const registryUsers: User[] = [ { title: 'Auto', description: 'Auto-detection client for determining optimal communication channels.', - preview: '/eliza/logos/auto.jpg', + preview: '/logos/auto.jpg', website: 'https://github.com/elizaos-plugins/client-auto', source: 'https://github.com/elizaos-plugins/client-auto', tags: ['client'], @@ -70,7 +70,7 @@ export const registryUsers: User[] = [ title: 'Discord', description: 'Discord integration client with messaging and community interaction capabilities.', - preview: '/eliza/logos/discord.jpg', + preview: '/logos/discord.jpg', website: 'https://github.com/elizaos-plugins/client-discord', source: 'https://github.com/elizaos-plugins/client-discord', tags: ['client', 'favorite'], @@ -78,7 +78,7 @@ export const registryUsers: User[] = [ { title: 'Farcaster', description: 'Client for Farcaster decentralized social media protocol.', - preview: '/eliza/logos/farcaster.jpg', + preview: '/logos/farcaster.jpg', website: 'https://github.com/elizaos-plugins/client-farcaster', source: 'https://github.com/elizaos-plugins/client-farcaster', tags: ['client'], @@ -86,7 +86,7 @@ export const registryUsers: User[] = [ { title: 'Github', description: 'GitHub client for repository management and code integration.', - preview: '/eliza/logos/github.png', + preview: '/logos/github.png', website: 'https://github.com/elizaos-plugins/client-github', source: 'https://github.com/elizaos-plugins/client-github', tags: ['client', 'favorite'], @@ -94,7 +94,7 @@ export const registryUsers: User[] = [ { title: 'Lens', description: 'Client for Lens Protocol decentralized social networking.', - preview: '/eliza/logos/lens.jpg', + preview: '/logos/lens.jpg', website: 'https://github.com/elizaos-plugins/client-lens', source: 'https://github.com/elizaos-plugins/client-lens', tags: ['client'], @@ -102,7 +102,7 @@ export const registryUsers: User[] = [ { title: 'Slack', description: 'Slack integration client with messaging and workspace collaboration features.', - preview: '/eliza/logos/slack.jpg', + preview: '/logos/slack.jpg', website: 'https://github.com/elizaos-plugins/client-slack', source: 'https://github.com/elizaos-plugins/client-slack', tags: ['client'], @@ -110,7 +110,7 @@ export const registryUsers: User[] = [ { title: 'Telegram', description: 'Telegram messaging client with bot and channel integration capabilities.', - preview: '/eliza/logos/telegram.jpg', + preview: '/logos/telegram.jpg', website: 'https://github.com/elizaos-plugins/client-telegram', source: 'https://github.com/elizaos-plugins/client-telegram', tags: ['client', 'favorite'], @@ -118,7 +118,7 @@ export const registryUsers: User[] = [ { title: 'Twitter', description: 'Twitter/X client for posting and monitoring social media activity.', - preview: '/eliza/logos/x.jpg', + preview: '/logos/x.jpg', website: 'https://github.com/elizaos-plugins/client-twitter', source: 'https://github.com/elizaos-plugins/client-twitter', tags: ['client', 'favorite'], @@ -126,7 +126,7 @@ export const registryUsers: User[] = [ { title: 'Tako', description: 'Client for the Tako protocol enabling cross-platform social engagement.', - preview: '/eliza/logos/tako.png', + preview: '/logos/tako.png', website: 'https://github.com/takoprotocol/client-tako', source: 'https://github.com/takoprotocol/client-tako', tags: ['client'], @@ -135,7 +135,7 @@ export const registryUsers: User[] = [ title: '0g', description: 'Provides decentralized file storage capabilities using the Zero Gravity (0G) protocol.', - preview: '/eliza/logos/0g.jpg', + preview: '/logos/0g.jpg', website: 'https://github.com/elizaos-plugins/plugin-0g', source: 'https://github.com/elizaos-plugins/plugin-0g', tags: ['plugin'], @@ -143,7 +143,7 @@ export const registryUsers: User[] = [ { title: '3d Generation', description: "Generates 3D models from text descriptions using FAL.ai's API services.", - preview: '/eliza/logos/falai.png', + preview: '/logos/falai.png', website: 'https://github.com/elizaos-plugins/plugin-3d-generation', source: 'https://github.com/elizaos-plugins/plugin-3d-generation', tags: ['plugin'], @@ -151,7 +151,7 @@ export const registryUsers: User[] = [ { title: 'Abstract', description: 'Enables token transfers and operations on the Abstract blockchain network.', - preview: '/eliza/logos/abstract.jpg', + preview: '/logos/abstract.jpg', website: 'https://github.com/elizaos-plugins/plugin-abstract', source: 'https://github.com/elizaos-plugins/plugin-abstract', tags: ['plugin'], @@ -159,7 +159,7 @@ export const registryUsers: User[] = [ { title: 'Akash', description: 'Manages deployments and cloud compute operations on the Akash Network.', - preview: '/eliza/logos/akash.jpg', + preview: '/logos/akash.jpg', website: 'https://github.com/elizaos-plugins/plugin-akash', source: 'https://github.com/elizaos-plugins/plugin-akash', tags: ['plugin'], @@ -168,7 +168,7 @@ export const registryUsers: User[] = [ title: 'Allora', description: 'Provides real-time AI inferences from the Allora Network for market predictions and analysis.', - preview: '/eliza/logos/allora.jpg', + preview: '/logos/allora.jpg', website: 'https://github.com/elizaos-plugins/plugin-allora', source: 'https://github.com/elizaos-plugins/plugin-allora', tags: ['plugin'], @@ -176,7 +176,7 @@ export const registryUsers: User[] = [ { title: 'Anyone', description: 'Enables SOCKS proxy configuration for the Anyone protocol proxy services.', - preview: '/eliza/logos/anyone.jpg', + preview: '/logos/anyone.jpg', website: 'https://github.com/elizaos-plugins/plugin-anyone', source: 'https://github.com/elizaos-plugins/plugin-anyone', tags: ['plugin'], @@ -184,7 +184,7 @@ export const registryUsers: User[] = [ { title: 'Aptos', description: 'Handles token transfers and wallet management on the Aptos blockchain.', - preview: '/eliza/logos/aptos.jpg', + preview: '/logos/aptos.jpg', website: 'https://github.com/elizaos-plugins/plugin-aptos', source: 'https://github.com/elizaos-plugins/plugin-aptos', tags: ['plugin'], @@ -192,7 +192,7 @@ export const registryUsers: User[] = [ { title: 'Arthera', description: 'Facilitates transactions and token operations on the Arthera network.', - preview: '/eliza/logos/arthera.jpg', + preview: '/logos/arthera.jpg', website: 'https://github.com/elizaos-plugins/plugin-arthera', source: 'https://github.com/elizaos-plugins/plugin-arthera', tags: ['plugin'], @@ -200,7 +200,7 @@ export const registryUsers: User[] = [ { title: 'Asterai', description: 'Integrates with asterai.io plugins and agents for enhanced AI capabilities.', - preview: '/eliza/logos/asterai.jpg', + preview: '/logos/asterai.jpg', website: 'https://github.com/elizaos-plugins/plugin-asterai', source: 'https://github.com/elizaos-plugins/plugin-asterai', tags: ['plugin'], @@ -208,7 +208,7 @@ export const registryUsers: User[] = [ { title: 'ATTPs', description: 'Enables verification of agent activities using proof generation and validation.', - preview: '/eliza/logos/appro.jpg', + preview: '/logos/appro.jpg', website: 'https://github.com/APRO-com/plugin-ATTPs', source: 'https://github.com/APRO-com/plugin-ATTPs', tags: ['plugin'], @@ -216,7 +216,7 @@ export const registryUsers: User[] = [ { title: 'Autonome', description: 'Launches and manages new Eliza agents through the Autonome platform.', - preview: '/eliza/logos/autonome.jpg', + preview: '/logos/autonome.jpg', website: 'https://github.com/elizaos-plugins/plugin-autonome', source: 'https://github.com/elizaos-plugins/plugin-autonome', tags: ['plugin'], @@ -224,7 +224,7 @@ export const registryUsers: User[] = [ { title: 'Avail', description: 'Interacts with Avail DA network for data availability and token transfers.', - preview: '/eliza/logos/avail.png', + preview: '/logos/avail.png', website: 'https://github.com/elizaos-plugins/plugin-avail', source: 'https://github.com/elizaos-plugins/plugin-avail', tags: ['plugin'], @@ -232,7 +232,7 @@ export const registryUsers: User[] = [ { title: 'Avalanche', description: 'Enables DeFi operations and token management on the Avalanche blockchain.', - preview: '/eliza/logos/avalanche.jpg', + preview: '/logos/avalanche.jpg', website: 'https://github.com/elizaos-plugins/plugin-avalanche', source: 'https://github.com/elizaos-plugins/plugin-avalanche', tags: ['plugin'], @@ -241,7 +241,7 @@ export const registryUsers: User[] = [ title: 'Binance', description: "Provides cryptocurrency trading and price checking capabilities through Binance's API.", - preview: '/eliza/logos/binance.jpg', + preview: '/logos/binance.jpg', website: 'https://github.com/elizaos-plugins/plugin-binance', source: 'https://github.com/elizaos-plugins/plugin-binance', tags: ['plugin'], @@ -250,7 +250,7 @@ export const registryUsers: User[] = [ title: 'Ccxt', description: 'Enables cryptocurrency trading and arbitrage across multiple exchanges using CCXT.', - preview: '/eliza/logos/ccxt.png', + preview: '/logos/ccxt.png', website: 'https://github.com/pranavjadhav1363/plugin-ccxt', source: 'https://github.com/pranavjadhav1363/plugin-ccxt', tags: ['plugin'], @@ -259,7 +259,7 @@ export const registryUsers: User[] = [ title: 'Coinbase', description: "Provides comprehensive integration with Coinbase's various APIs and trading services.", - preview: '/eliza/logos/coinbase.png', + preview: '/logos/coinbase.png', website: 'https://github.com/elizaos-plugins/plugin-coinbase', source: 'https://github.com/elizaos-plugins/plugin-coinbase', tags: ['plugin'], @@ -267,7 +267,7 @@ export const registryUsers: User[] = [ { title: 'Coingecko', description: "Fetches cryptocurrency price data and market information from CoinGecko's API.", - preview: '/eliza/logos/coingecko.jpg', + preview: '/logos/coingecko.jpg', website: 'https://github.com/elizaos-plugins/plugin-coingecko', source: 'https://github.com/elizaos-plugins/plugin-coingecko', tags: ['plugin'], @@ -275,7 +275,7 @@ export const registryUsers: User[] = [ { title: 'Coinmarketcap', description: "Enables cryptocurrency price checking using CoinMarketCap's API services.", - preview: '/eliza/logos/coinmarketcap.jpg', + preview: '/logos/coinmarketcap.jpg', website: 'https://github.com/elizaos-plugins/plugin-coinmarketcap', source: 'https://github.com/elizaos-plugins/plugin-coinmarketcap', tags: ['plugin'], @@ -283,7 +283,7 @@ export const registryUsers: User[] = [ { title: 'Compass', description: 'Integrates with Compass API for executing operations on DeFi protocols.', - preview: '/eliza/logos/compass.jpg', + preview: '/logos/compass.jpg', website: 'https://github.com/CompassLabs/plugin-compass', source: 'https://github.com/CompassLabs/plugin-compass', tags: ['plugin'], @@ -291,7 +291,7 @@ export const registryUsers: User[] = [ { title: 'Conflux', description: 'Manages token transfers and interactions on the Conflux blockchain network.', - preview: '/eliza/logos/conflux.png', + preview: '/logos/conflux.png', website: 'https://github.com/elizaos-plugins/plugin-conflux', source: 'https://github.com/elizaos-plugins/plugin-conflux', tags: ['plugin'], @@ -299,7 +299,7 @@ export const registryUsers: User[] = [ { title: 'Cosmos', description: 'Handles token management and transfers using Cosmos-compatible blockchains.', - preview: '/eliza/logos/cosmos.jpg', + preview: '/logos/cosmos.jpg', website: 'https://github.com/elizaos-plugins/plugin-cosmos', source: 'https://github.com/elizaos-plugins/plugin-cosmos', tags: ['plugin'], @@ -307,7 +307,7 @@ export const registryUsers: User[] = [ { title: 'Cronoszkevm', description: 'Enables token transfers and interactions on the Cronos zkEVM network.', - preview: '/eliza/logos/cronos.png', + preview: '/logos/cronos.png', website: 'https://github.com/elizaos-plugins/plugin-cronoszkevm', source: 'https://github.com/elizaos-plugins/plugin-cronoszkevm', tags: ['plugin'], @@ -316,7 +316,7 @@ export const registryUsers: User[] = [ title: 'D.a.t.a', description: 'Processes and analyzes data from various sources with authentication and trust scoring.', - preview: '/eliza/logos/carv.jpg', + preview: '/logos/carv.jpg', website: 'https://github.com/carv-protocol/plugin-d.a.t.a', source: 'https://github.com/carv-protocol/plugin-d.a.t.a', tags: ['plugin'], @@ -324,7 +324,7 @@ export const registryUsers: User[] = [ { title: 'Dcap', description: 'Provides Intel Data Center Attestation Primitives for secure cloud environments.', - preview: '/eliza/logos/dcap.png', + preview: '/logos/dcap.png', website: 'https://github.com/elizaos-plugins/plugin-dcap', source: 'https://github.com/elizaos-plugins/plugin-dcap', tags: ['plugin'], @@ -333,7 +333,7 @@ export const registryUsers: User[] = [ title: 'Depin', description: 'Connects AI agents to physical infrastructure through Decentralized Physical Infrastructure Networks.', - preview: '/eliza/logos/depin.jpg', + preview: '/logos/depin.jpg', website: 'https://github.com/elizaos-plugins/plugin-depin', source: 'https://github.com/elizaos-plugins/plugin-depin', tags: ['plugin'], @@ -341,7 +341,7 @@ export const registryUsers: User[] = [ { title: 'Di', description: 'Provides dependency injection system for Eliza plugins.', - preview: '/eliza/logos/di-logo.jpg', + preview: '/logos/di-logo.jpg', website: 'https://github.com/fixes-world/plugin-di', source: 'https://github.com/fixes-world/plugin-di', tags: ['plugin'], @@ -350,7 +350,7 @@ export const registryUsers: User[] = [ title: 'Echochambers', description: 'Enables chat room interactions with dynamic conversation handling and monitoring.', - preview: '/eliza/logos/echochambers.png', + preview: '/logos/echochambers.png', website: 'https://github.com/elizaos-plugins/plugin-echochambers', source: 'https://github.com/elizaos-plugins/plugin-echochambers', tags: ['plugin'], @@ -358,7 +358,7 @@ export const registryUsers: User[] = [ { title: 'Edwin', description: 'Enables interaction with Edwin tools for DeFi operations.', - preview: '/eliza/logos/edwin.jpg', + preview: '/logos/edwin.jpg', website: 'https://github.com/elizaos-plugins/plugin-edwin', source: 'https://github.com/elizaos-plugins/plugin-edwin', tags: ['plugin'], @@ -366,7 +366,7 @@ export const registryUsers: User[] = [ { title: 'Evm', description: 'Provides comprehensive functionality for interacting with EVM-compatible chains.', - preview: '/eliza/logos/evm.png', + preview: '/logos/evm.png', website: 'https://github.com/elizaos-plugins/plugin-evm', source: 'https://github.com/elizaos-plugins/plugin-evm', tags: ['plugin', 'favorite'], @@ -374,7 +374,7 @@ export const registryUsers: User[] = [ { title: 'FerePro', description: 'Enables WebSocket communication with FerePro API for AI-driven market insights.', - preview: '/eliza/logos/ferepro.png', + preview: '/logos/ferepro.png', website: 'https://github.com/elizaos-plugins/plugin-ferePro', source: 'https://github.com/elizaos-plugins/plugin-ferePro', tags: ['plugin'], @@ -382,7 +382,7 @@ export const registryUsers: User[] = [ { title: 'Firecrawl', description: 'Provides web scraping and crawling capabilities through the Firecrawl API.', - preview: '/eliza/logos/firecrawl.jpg', + preview: '/logos/firecrawl.jpg', website: 'https://github.com/tobySolutions/plugin-firecrawl', source: 'https://github.com/tobySolutions/plugin-firecrawl', tags: ['plugin'], @@ -391,7 +391,7 @@ export const registryUsers: User[] = [ title: 'Flow', description: 'Manages Flow blockchain interactions including token transfers and smart contracts.', - preview: '/eliza/logos/flowchain.png', + preview: '/logos/flowchain.png', website: 'https://github.com/fixes-world/plugin-flow', source: 'https://github.com/fixes-world/plugin-flow', tags: ['plugin'], @@ -399,7 +399,7 @@ export const registryUsers: User[] = [ { title: 'Flow Advanced', description: 'The advanced Eliza plugin for Flow Blockchain', - preview: '/eliza/logos/flowchain.png', + preview: '/logos/flowchain.png', website: 'https://github.com/fixes-world/plugin-flow-advanced', source: 'https://github.com/fixes-world/plugin-flow-advanced', tags: ['plugin'], @@ -407,7 +407,7 @@ export const registryUsers: User[] = [ { title: 'Fuel', description: 'Enables ETH transfers and interactions on the Fuel Ignition network.', - preview: '/eliza/logos/fuel.jpg', + preview: '/logos/fuel.jpg', website: 'https://github.com/elizaos-plugins/plugin-fuel', source: 'https://github.com/elizaos-plugins/plugin-fuel', tags: ['plugin'], @@ -415,7 +415,7 @@ export const registryUsers: User[] = [ { title: 'Genlayer', description: 'Facilitates contract deployment and interactions on the GenLayer protocol.', - preview: '/eliza/logos/genlayer.jpg', + preview: '/logos/genlayer.jpg', website: 'https://github.com/elizaos-plugins/plugin-genlayer', source: 'https://github.com/elizaos-plugins/plugin-genlayer', tags: ['plugin'], @@ -423,7 +423,7 @@ export const registryUsers: User[] = [ { title: 'Gigbot', description: 'AI-powered freelance work management and automation toolkit.', - preview: '/eliza/logos/gigbot.png', + preview: '/logos/gigbot.png', website: 'https://github.com/PaymagicXYZ/plugin-gigbot', source: 'https://github.com/PaymagicXYZ/plugin-gigbot', tags: ['plugin'], @@ -431,7 +431,7 @@ export const registryUsers: User[] = [ { title: 'Giphy', description: 'Enables sending GIFs in response to user messages using the Giphy API.', - preview: '/eliza/logos/giphy.jpg', + preview: '/logos/giphy.jpg', website: 'https://github.com/elizaos-plugins/plugin-giphy', source: 'https://github.com/elizaos-plugins/plugin-giphy', tags: ['plugin'], @@ -439,7 +439,7 @@ export const registryUsers: User[] = [ { title: 'Gitbook', description: 'Enables querying and retrieving information from GitBook documentation.', - preview: '/eliza/logos/gitbook.jpg', + preview: '/logos/gitbook.jpg', website: 'https://github.com/elizaos-plugins/plugin-gitbook', source: 'https://github.com/elizaos-plugins/plugin-gitbook', tags: ['plugin'], @@ -448,7 +448,7 @@ export const registryUsers: User[] = [ title: 'Goat', description: 'Integrates blockchain capabilities through the GOAT (Great Onchain Agent Toolkit) framework.', - preview: '/eliza/logos/goat.jpg', + preview: '/logos/goat.jpg', website: 'https://github.com/elizaos-plugins/plugin-goat', source: 'https://github.com/elizaos-plugins/plugin-goat', tags: ['plugin'], @@ -456,7 +456,7 @@ export const registryUsers: User[] = [ { title: 'Goplus', description: 'Enables on-chain security checks through the GoPlus API integration.', - preview: '/eliza/logos/goplus.jpg', + preview: '/logos/goplus.jpg', website: 'https://github.com/elizaos-plugins/plugin-goplus', source: 'https://github.com/elizaos-plugins/plugin-goplus', tags: ['plugin'], @@ -464,7 +464,7 @@ export const registryUsers: User[] = [ { title: 'Grix', description: 'Enables DeFi options data fetching and price analysis through Grix Finance API.', - preview: '/eliza/logos/grix.png', + preview: '/logos/grix.png', website: 'https://github.com/grixprotocol/plugin-grix', source: 'https://github.com/grixprotocol/plugin-grix', tags: ['plugin'], @@ -472,7 +472,7 @@ export const registryUsers: User[] = [ { title: 'Hyperliquid', description: 'Provides spot trading capabilities on the Hyperliquid DEX.', - preview: '/eliza/logos/hyperliquid.png', + preview: '/logos/hyperliquid.png', website: 'https://github.com/elizaos-plugins/plugin-hyperliquid', source: 'https://github.com/elizaos-plugins/plugin-hyperliquid', tags: ['plugin'], @@ -481,7 +481,7 @@ export const registryUsers: User[] = [ title: 'Icp', description: 'Enables interaction with Internet Computer Protocol for token and smart contract operations.', - preview: '/eliza/logos/ICP.jpg', + preview: '/logos/ICP.jpg', website: 'https://github.com/elizaos-plugins/plugin-icp', source: 'https://github.com/elizaos-plugins/plugin-icp', tags: ['plugin'], @@ -489,7 +489,7 @@ export const registryUsers: User[] = [ { title: 'Image Generation', description: 'Generates and manages images with storage integration and optimization features.', - preview: '/eliza/logos/imagegen.jpg', + preview: '/logos/imagegen.jpg', website: 'https://github.com/elizaos-plugins/plugin-image-generation', source: 'https://github.com/elizaos-plugins/plugin-image-generation', tags: ['plugin'], @@ -497,7 +497,7 @@ export const registryUsers: User[] = [ { title: 'Intiface', description: 'Controls intimate hardware devices through the Buttplug.io protocol.', - preview: '/eliza/logos/intiface.png', + preview: '/logos/intiface.png', website: 'https://github.com/elizaos-plugins/plugin-intiface', source: 'https://github.com/elizaos-plugins/plugin-intiface', tags: ['plugin'], @@ -506,7 +506,7 @@ export const registryUsers: User[] = [ title: 'Irys', description: 'Enables decentralized data storage and retrieval using the Irys datachain platform.', - preview: '/eliza/logos/irys.jpg', + preview: '/logos/irys.jpg', website: 'https://github.com/elizaos-plugins/plugin-irys', source: 'https://github.com/elizaos-plugins/plugin-irys', tags: ['plugin'], @@ -514,7 +514,7 @@ export const registryUsers: User[] = [ { title: 'Isaacx', description: 'Advanced AI reasoning and cognitive modeling plugin.', - preview: '/eliza/logos/isaac.jpg', + preview: '/logos/isaac.jpg', website: 'https://github.com/isaacx0/plugin-isaacx', source: 'https://github.com/isaacx0/plugin-isaacx', tags: ['plugin'], @@ -522,7 +522,7 @@ export const registryUsers: User[] = [ { title: 'Letzai', description: "Enables image generation using LetzAI's API and models.", - preview: '/eliza/logos/letzai.jpg', + preview: '/logos/letzai.jpg', website: 'https://github.com/elizaos-plugins/plugin-letzai', source: 'https://github.com/elizaos-plugins/plugin-letzai', tags: ['plugin'], @@ -530,7 +530,7 @@ export const registryUsers: User[] = [ { title: 'Lightlink', description: 'Enables Ethereum layer 2 operations on the Lightlink blockchain network.', - preview: '/eliza/logos/lightlink.jpg', + preview: '/logos/lightlink.jpg', website: 'https://github.com/lightlink-network/plugin-lightlink', source: 'https://github.com/lightlink-network/plugin-lightlink', tags: ['plugin'], @@ -538,7 +538,7 @@ export const registryUsers: User[] = [ { title: 'Massa', description: 'Enables interactions with the Massa blockchain ecosystem.', - preview: '/eliza/logos/massa.jpg', + preview: '/logos/massa.jpg', website: 'https://github.com/elizaos-plugins/plugin-massa', source: 'https://github.com/elizaos-plugins/plugin-massa', tags: ['plugin'], @@ -547,7 +547,7 @@ export const registryUsers: User[] = [ title: 'Merkle', description: 'Integrates MerkleTrade platform for trading operations with API-based price tracking and order management.', - preview: '/eliza/logos/merkle.jpg', + preview: '/logos/merkle.jpg', website: 'https://github.com/merkle-trade/merkle-eliza-plugin', source: 'https://github.com/merkle-trade/merkle-eliza-plugin', tags: ['plugin'], @@ -555,7 +555,7 @@ export const registryUsers: User[] = [ { title: 'Messari Ai Toolkit', description: "Provides crypto market research capabilities using Messari's AI Toolkit.", - preview: '/eliza/logos/messari.jpg', + preview: '/logos/messari.jpg', website: 'https://github.com/messari/plugin-messari-ai-toolkit', source: 'https://github.com/messari/plugin-messari-ai-toolkit', tags: ['plugin'], @@ -563,7 +563,7 @@ export const registryUsers: User[] = [ { title: 'Movement', description: 'Enables Movement Network blockchain functionality for token operations.', - preview: '/eliza/logos/movement.jpg', + preview: '/logos/movement.jpg', website: 'https://github.com/elizaos-plugins/plugin-movement', source: 'https://github.com/elizaos-plugins/plugin-movement', tags: ['plugin'], @@ -571,7 +571,7 @@ export const registryUsers: User[] = [ { title: 'Multichain', description: 'Cross-chain interaction capabilities for multiple blockchain networks.', - preview: '/eliza/logos/nearai.png', + preview: '/logos/nearai.png', website: 'https://github.com/near-agent/elizaos-plugin-multichain', source: 'https://github.com/near-agent/elizaos-plugin-multichain', tags: ['plugin'], @@ -579,7 +579,7 @@ export const registryUsers: User[] = [ { title: 'Multiversx', description: 'Manages token operations and transfers on the MultiversX blockchain.', - preview: '/eliza/logos/multiversx.jpg', + preview: '/logos/multiversx.jpg', website: 'https://github.com/elizaos-plugins/plugin-multiversx', source: 'https://github.com/elizaos-plugins/plugin-multiversx', tags: ['plugin'], @@ -587,7 +587,7 @@ export const registryUsers: User[] = [ { title: 'Near', description: 'Enables token management and transfers on the NEAR Protocol blockchain.', - preview: '/eliza/logos/NEAR.jpg', + preview: '/logos/NEAR.jpg', website: 'https://github.com/elizaos-plugins/plugin-near', source: 'https://github.com/elizaos-plugins/plugin-near', tags: ['plugin'], @@ -595,7 +595,7 @@ export const registryUsers: User[] = [ { title: 'Nft Generation', description: 'Creates NFT collections with AI-generated artwork on the Solana blockchain.', - preview: '/eliza/logos/nftgen.png', + preview: '/logos/nftgen.png', website: 'https://github.com/elizaos-plugins/plugin-nft-generation', source: 'https://github.com/elizaos-plugins/plugin-nft-generation', tags: ['plugin'], @@ -603,7 +603,7 @@ export const registryUsers: User[] = [ { title: 'Node', description: 'Provides core Node.js services for file operations and media processing.', - preview: '/eliza/logos/nodejs.jpg', + preview: '/logos/nodejs.jpg', website: 'https://github.com/elizaos-plugins/plugin-node', source: 'https://github.com/elizaos-plugins/plugin-node', tags: ['plugin'], @@ -612,7 +612,7 @@ export const registryUsers: User[] = [ title: 'Nkn', description: 'Enables communication between multiple AI agents using the NKN protocol for decentralized messaging.', - preview: '/eliza/logos/nkn.jpg', + preview: '/logos/nkn.jpg', website: 'https://github.com/nknorg/eliza-plugin-nkn', source: 'https://github.com/nknorg/eliza-plugin-nkn', tags: ['plugin'], @@ -620,7 +620,7 @@ export const registryUsers: User[] = [ { title: 'Obsidian', description: 'Enables seamless integration with Obsidian vaults for note management.', - preview: '/eliza/logos/obsidian.jpg', + preview: '/logos/obsidian.jpg', website: 'https://github.com/elizaos-plugins/plugin-obsidian', source: 'https://github.com/elizaos-plugins/plugin-obsidian', tags: ['plugin'], @@ -628,7 +628,7 @@ export const registryUsers: User[] = [ { title: 'Okto', description: 'Self-custody wallet operations and transaction management.', - preview: '/eliza/logos/okto.png', + preview: '/logos/okto.png', website: 'https://github.com/okto-hq/eliza-plugin', source: 'https://github.com/okto-hq/eliza-plugin', tags: ['plugin'], @@ -636,7 +636,7 @@ export const registryUsers: User[] = [ { title: 'Okx', description: 'Trading and asset management through OKX exchange API.', - preview: '/eliza/logos/okx.png', + preview: '/logos/okx.png', website: 'https://github.com/elizaos-plugins/plugin-okx', source: 'https://github.com/elizaos-plugins/plugin-okx', tags: ['plugin'], @@ -644,7 +644,7 @@ export const registryUsers: User[] = [ { title: 'Omniflix', description: 'Facilitates interactions with the OmniFlix Network blockchain.', - preview: '/eliza/logos/omniflix.jpg', + preview: '/logos/omniflix.jpg', website: 'https://github.com/elizaos-plugins/plugin-omniflix', source: 'https://github.com/elizaos-plugins/plugin-omniflix', tags: ['plugin'], @@ -652,7 +652,7 @@ export const registryUsers: User[] = [ { title: 'Opacity', description: 'Implements verifiable inference results from various AI model providers.', - preview: '/eliza/logos/opacity.jpg', + preview: '/logos/opacity.jpg', website: 'https://github.com/elizaos-plugins/plugin-opacity', source: 'https://github.com/elizaos-plugins/plugin-opacity', tags: ['plugin'], @@ -660,7 +660,7 @@ export const registryUsers: User[] = [ { title: 'Open Weather', description: 'Fetches weather data using the OpenWeather API.', - preview: '/eliza/logos/openweather.jpg', + preview: '/logos/openweather.jpg', website: 'https://github.com/elizaos-plugins/plugin-open-weather', source: 'https://github.com/elizaos-plugins/plugin-open-weather', tags: ['plugin'], @@ -668,7 +668,7 @@ export const registryUsers: User[] = [ { title: 'Primus', description: "Verifies agent activities using Primus' zkTLS protocol.", - preview: '/eliza/logos/primus.png', + preview: '/logos/primus.png', website: 'https://github.com/elizaos-plugins/plugin-primus', source: 'https://github.com/elizaos-plugins/plugin-primus', tags: ['plugin'], @@ -676,7 +676,7 @@ export const registryUsers: User[] = [ { title: 'Quai', description: 'Enables token transfers and blockchain interactions on Quai Network.', - preview: '/eliza/logos/quai.jpg', + preview: '/logos/quai.jpg', website: 'https://github.com/elizaos-plugins/plugin-quai', source: 'https://github.com/elizaos-plugins/plugin-quai', tags: ['plugin'], @@ -684,7 +684,7 @@ export const registryUsers: User[] = [ { title: 'Rabbi Trader', description: 'Provides automated cryptocurrency trading on Solana with trust scoring.', - preview: '/eliza/logos/rabbitrader.jpg', + preview: '/logos/rabbitrader.jpg', website: 'https://github.com/elizaos-plugins/plugin-rabbi-trader', source: 'https://github.com/elizaos-plugins/plugin-rabbi-trader', tags: ['plugin'], @@ -692,7 +692,7 @@ export const registryUsers: User[] = [ { title: 'Sei', description: 'Enables token transfers and operations on the Sei blockchain network.', - preview: '/eliza/logos/sei.jpg', + preview: '/logos/sei.jpg', website: 'https://github.com/elizaos-plugins/plugin-sei', source: 'https://github.com/elizaos-plugins/plugin-sei', tags: ['plugin'], @@ -700,7 +700,7 @@ export const registryUsers: User[] = [ { title: 'Sgx', description: 'Provides Intel SGX attestation capabilities for secure execution.', - preview: '/eliza/logos/intelsgx.png', + preview: '/logos/intelsgx.png', website: 'https://github.com/elizaos-plugins/plugin-sgx', source: 'https://github.com/elizaos-plugins/plugin-sgx', tags: ['plugin'], @@ -708,7 +708,7 @@ export const registryUsers: User[] = [ { title: 'Solana', description: 'Enables comprehensive DeFi operations on the Solana blockchain.', - preview: '/eliza/logos/solana.jpg', + preview: '/logos/solana.jpg', website: 'https://github.com/elizaos-plugins/plugin-solana', source: 'https://github.com/elizaos-plugins/plugin-solana', tags: ['plugin'], @@ -716,7 +716,7 @@ export const registryUsers: User[] = [ { title: 'Solana Agent Kit', description: 'Provides token operations and NFT functionality on Solana.', - preview: '/eliza/logos/sendai.png', + preview: '/logos/sendai.png', website: 'https://github.com/elizaos-plugins/plugin-solana-agent-kit', source: 'https://github.com/elizaos-plugins/plugin-solana-agent-kit', tags: ['plugin', 'favorite'], @@ -724,7 +724,7 @@ export const registryUsers: User[] = [ { title: 'Spheron', description: 'Manages deployments and operations using the Spheron Protocol.', - preview: '/eliza/logos/spheron.jpg', + preview: '/logos/spheron.jpg', website: 'https://github.com/elizaos-plugins/plugin-spheron', source: 'https://github.com/elizaos-plugins/plugin-spheron', tags: ['plugin'], @@ -732,7 +732,7 @@ export const registryUsers: User[] = [ { title: 'Stargaze', description: 'Fetches NFT data from Stargaze collections.', - preview: '/eliza/logos/stargaze.png', + preview: '/logos/stargaze.png', website: 'https://github.com/elizaos-plugins/plugin-stargaze', source: 'https://github.com/elizaos-plugins/plugin-stargaze', tags: ['plugin'], @@ -740,7 +740,7 @@ export const registryUsers: User[] = [ { title: 'Starknet', description: 'Enables token and DeFi operations on the Starknet blockchain.', - preview: '/eliza/logos/starknet.png', + preview: '/logos/starknet.png', website: 'https://github.com/elizaos-plugins/plugin-starknet', source: 'https://github.com/elizaos-plugins/plugin-starknet', tags: ['plugin'], @@ -749,7 +749,7 @@ export const registryUsers: User[] = [ title: 'Story', description: 'Generates and manages interactive storytelling experiences with branching narratives.', - preview: '/eliza/logos/story.jpg', + preview: '/logos/story.jpg', website: 'https://github.com/elizaos-plugins/plugin-story', source: 'https://github.com/elizaos-plugins/plugin-story', tags: ['plugin', 'favorite'], @@ -757,7 +757,7 @@ export const registryUsers: User[] = [ { title: 'Sui', description: 'Manages token transfers and wallet operations on the Sui blockchain.', - preview: '/eliza/logos/sui.jpg', + preview: '/logos/sui.jpg', website: 'https://github.com/elizaos-plugins/plugin-sui', source: 'https://github.com/elizaos-plugins/plugin-sui', tags: ['plugin'], @@ -765,7 +765,7 @@ export const registryUsers: User[] = [ { title: 'Tee', description: 'Handles Trusted Execution Environment operations and key management.', - preview: '/eliza/logos/phalatee.jpg', + preview: '/logos/phalatee.jpg', website: 'https://github.com/elizaos-plugins/plugin-tee', source: 'https://github.com/elizaos-plugins/plugin-tee', tags: ['plugin'], @@ -773,7 +773,7 @@ export const registryUsers: User[] = [ { title: 'Tee Log', description: 'Provides secure logging capabilities within Trusted Execution Environments.', - preview: '/eliza/logos/tee.png', + preview: '/logos/tee.png', website: 'https://github.com/elizaos-plugins/plugin-tee-log', source: 'https://github.com/elizaos-plugins/plugin-tee-log', tags: ['plugin'], @@ -781,7 +781,7 @@ export const registryUsers: User[] = [ { title: 'Tee Marlin', description: 'Enables TEE verification through Marlin Oyster platform.', - preview: '/eliza/logos/marlin.jpg', + preview: '/logos/marlin.jpg', website: 'https://github.com/elizaos-plugins/plugin-tee-marlin', source: 'https://github.com/elizaos-plugins/plugin-tee-marlin', tags: ['plugin'], @@ -789,7 +789,7 @@ export const registryUsers: User[] = [ { title: 'Thirdweb', description: "Provides access to thirdweb's Nebula AI interface.", - preview: '/eliza/logos/thirdweb.jpg', + preview: '/logos/thirdweb.jpg', website: 'https://github.com/elizaos-plugins/plugin-thirdweb', source: 'https://github.com/elizaos-plugins/plugin-thirdweb', tags: ['plugin'], @@ -797,7 +797,7 @@ export const registryUsers: User[] = [ { title: 'Ton', description: 'Manages TON blockchain operations and wallet functionality.', - preview: '/eliza/logos/ton.png', + preview: '/logos/ton.png', website: 'https://github.com/elizaos-plugins/plugin-ton', source: 'https://github.com/elizaos-plugins/plugin-ton', tags: ['plugin'], @@ -806,7 +806,7 @@ export const registryUsers: User[] = [ title: 'Trustgo', description: 'Enables fetching EVM account information and MEDIA score attestations from TrustGo.', - preview: '/eliza/logos/trusta.jpg', + preview: '/logos/trusta.jpg', website: 'https://github.com/TrustaLabs/plugin-trustgo', source: 'https://github.com/TrustaLabs/plugin-trustgo', tags: ['plugin'], @@ -814,7 +814,7 @@ export const registryUsers: User[] = [ { title: 'Tts', description: "Generates speech from text using FAL.ai's API.", - preview: '/eliza/logos/fal.jpg', + preview: '/logos/fal.jpg', website: 'https://github.com/elizaos-plugins/plugin-tts', source: 'https://github.com/elizaos-plugins/plugin-tts', tags: ['plugin'], @@ -822,7 +822,7 @@ export const registryUsers: User[] = [ { title: 'Twilio', description: 'SMS, voice, and communication capabilities through Twilio API.', - preview: '/eliza/logos/twilio.png', + preview: '/logos/twilio.png', website: 'https://github.com/boolkeys/plugin-twilio', source: 'https://github.com/boolkeys/plugin-twilio', tags: ['plugin'], @@ -830,7 +830,7 @@ export const registryUsers: User[] = [ { title: 'Twitter', description: 'Enables automated tweet posting with character-aware content generation.', - preview: '/eliza/logos/x.jpg', + preview: '/logos/x.jpg', website: 'https://github.com/elizaos-plugins/plugin-twitter', source: 'https://github.com/elizaos-plugins/plugin-twitter', tags: ['plugin'], @@ -839,7 +839,7 @@ export const registryUsers: User[] = [ title: 'Viction', description: 'Services and actions for token operations, trading, and DeFi integrations using Viction.', - preview: '/eliza/logos/viction.jpg', + preview: '/logos/viction.jpg', website: 'https://github.com/BuildOnViction/plugin-viction', source: 'https://github.com/BuildOnViction/plugin-viction', tags: ['plugin'], @@ -847,7 +847,7 @@ export const registryUsers: User[] = [ { title: 'Video Generation', description: "Generates videos using Luma AI's API services.", - preview: '/eliza/logos/LUMA.jpg', + preview: '/logos/LUMA.jpg', website: 'https://github.com/elizaos-plugins/plugin-video-generation', source: 'https://github.com/elizaos-plugins/plugin-video-generation', tags: ['plugin'], @@ -855,7 +855,7 @@ export const registryUsers: User[] = [ { title: 'Web Search', description: 'Provides powerful web search capabilities with customizable API interface.', - preview: '/eliza/logos/websearch.jpg', + preview: '/logos/websearch.jpg', website: 'https://github.com/elizaos-plugins/plugin-web-search', source: 'https://github.com/elizaos-plugins/plugin-web-search', tags: ['plugin'], @@ -863,7 +863,7 @@ export const registryUsers: User[] = [ { title: 'Whatsapp', description: 'Enables WhatsApp messaging through the Cloud API with comprehensive features.', - preview: '/eliza/logos/whatsapp.png', + preview: '/logos/whatsapp.png', website: 'https://github.com/elizaos-plugins/plugin-whatsapp', source: 'https://github.com/elizaos-plugins/plugin-whatsapp', tags: ['plugin'], @@ -871,7 +871,7 @@ export const registryUsers: User[] = [ { title: 'Youtube To Text', description: 'Converts YouTube videos to text transcripts.', - preview: '/eliza/logos/youtube.png', + preview: '/logos/youtube.png', website: 'https://github.com/wellaios/plugin-youtube-to-text', source: 'https://github.com/wellaios/plugin-youtube-to-text', tags: ['plugin'], @@ -879,7 +879,7 @@ export const registryUsers: User[] = [ { title: 'Zapper', description: 'Portfolio tracking and DeFi position management across multiple chains.', - preview: '/eliza/logos/zapper.jpg', + preview: '/logos/zapper.jpg', website: 'https://github.com/ben-dh3/plugin-zapper', source: 'https://github.com/ben-dh3/plugin-zapper', tags: ['plugin'], @@ -887,7 +887,7 @@ export const registryUsers: User[] = [ { title: 'Zerion', description: 'Fetches wallet portfolio and position data using the Zerion API.', - preview: '/eliza/logos/zerion.jpg', + preview: '/logos/zerion.jpg', website: 'https://github.com/elizaos-plugins/plugin-zerion', source: 'https://github.com/elizaos-plugins/plugin-zerion', tags: ['plugin'], @@ -895,7 +895,7 @@ export const registryUsers: User[] = [ { title: 'Zksync Era', description: 'Enables token transfers and operations on the zkSync Era network.', - preview: '/eliza/logos/zksync.jpg', + preview: '/logos/zksync.jpg', website: 'https://github.com/elizaos-plugins/plugin-zksync-era', source: 'https://github.com/elizaos-plugins/plugin-zksync-era', tags: ['plugin'], @@ -903,7 +903,7 @@ export const registryUsers: User[] = [ { title: 'Para', description: 'NFT and digital collectible management platform integration.', - preview: '/eliza/logos/para.png', + preview: '/logos/para.png', website: 'https://github.com/aipop-fun/plugin-para', source: 'https://github.com/aipop-fun/plugin-para', tags: ['plugin'], @@ -912,7 +912,7 @@ export const registryUsers: User[] = [ title: 'cache Redis', description: 'Unmaintained cache plugin that originally lived in @elizaos/core and needs a maintainer.', - preview: '/eliza/logos/redis.jpg', + preview: '/logos/redis.jpg', website: 'https://github.com/elizaos-plugins/cache-redis', source: 'https://github.com/elizaos-plugins/cache-redis', tags: ['plugin'], @@ -921,7 +921,7 @@ export const registryUsers: User[] = [ title: 'Alexa', description: 'Provides integration with Amazon Alexa devices for voice-controlled agent interactions.', - preview: '/eliza/logos/alexa.png', + preview: '/logos/alexa.png', website: 'https://github.com/elizaos-plugins/client-alexa', source: 'https://github.com/elizaos-plugins/client-alexa', tags: ['client'], @@ -930,7 +930,7 @@ export const registryUsers: User[] = [ title: 'Deva', description: 'Enables communication with Deva AI systems for advanced conversational capabilities.', - preview: '/eliza/logos/deva.jpg', + preview: '/logos/deva.jpg', website: 'https://github.com/elizaos-plugins/client-deva', source: 'https://github.com/elizaos-plugins/client-deva', tags: ['client'], @@ -938,7 +938,7 @@ export const registryUsers: User[] = [ { title: 'Direct', description: 'Deprecated plugin that now lives in @elizaos/core.', - preview: '/eliza/logos/direct.png', + preview: '/logos/direct.png', website: 'https://github.com/elizaos-plugins/client-direct', source: 'https://github.com/elizaos-plugins/client-direct', tags: ['client'], @@ -947,7 +947,7 @@ export const registryUsers: User[] = [ title: 'Eliza Home', description: 'Provides integration with Eliza Home environment for home automation and intelligent assistant features.', - preview: '/eliza/logos/home-assistant.png', + preview: '/logos/home-assistant.png', website: 'https://github.com/elizaos-plugins/client-eliza-home', source: 'https://github.com/elizaos-plugins/client-eliza-home', tags: ['client'], @@ -956,7 +956,7 @@ export const registryUsers: User[] = [ title: 'Instagram', description: 'Enables Instagram integration with support for media posting, comment handling, and interaction management.', - preview: '/eliza/logos/instagram.jpg', + preview: '/logos/instagram.jpg', website: 'https://github.com/elizaos-plugins/client-instagram', source: 'https://github.com/elizaos-plugins/client-instagram', tags: ['client'], @@ -964,7 +964,7 @@ export const registryUsers: User[] = [ { title: 'Simsai', description: 'Deprecated plugin that needs a maintainer.', - preview: '/eliza/logos/simsAI.jpg', + preview: '/logos/simsAI.jpg', website: 'https://github.com/elizaos-plugins/client-simsai', source: 'https://github.com/elizaos-plugins/client-simsai', tags: ['client'], @@ -973,7 +973,7 @@ export const registryUsers: User[] = [ title: 'Telegram Account', description: 'Provides advanced Telegram account management capabilities beyond basic bot functionality.', - preview: '/eliza/logos/telegram.jpg', + preview: '/logos/telegram.jpg', website: 'https://github.com/elizaos-plugins/client-telegram-account', source: 'https://github.com/elizaos-plugins/client-telegram-account', tags: ['client'], @@ -982,7 +982,7 @@ export const registryUsers: User[] = [ title: 'Xmtp', description: 'Enables secure, decentralized, and end-to-end encrypted messaging through the XMTP protocol.', - preview: '/eliza/logos/xmtp.jpg', + preview: '/logos/xmtp.jpg', website: 'https://github.com/elizaos-plugins/client-xmtp', source: 'https://github.com/elizaos-plugins/client-xmtp', tags: ['client'], @@ -991,7 +991,7 @@ export const registryUsers: User[] = [ title: '0x', description: 'Enables token swaps through 0x Protocol across multiple EVM blockchains with optimized routing and liquidity aggregation.', - preview: '/eliza/logos/0x.jpg', + preview: '/logos/0x.jpg', website: 'https://github.com/elizaos-plugins/plugin-0x', source: 'https://github.com/elizaos-plugins/plugin-0x', tags: ['plugin'], @@ -1000,7 +1000,7 @@ export const registryUsers: User[] = [ title: 'Agentkit', description: 'Integrates CDP AgentKit tools for NFT and token management on various blockchain networks.', - preview: '/eliza/logos/agentkitCDB.jpg', + preview: '/logos/agentkitCDB.jpg', website: 'https://github.com/elizaos-plugins/plugin-agentkit', source: 'https://github.com/elizaos-plugins/plugin-agentkit', tags: ['plugin'], @@ -1009,7 +1009,7 @@ export const registryUsers: User[] = [ title: 'Ankr', description: 'Provides blockchain data query interfaces for wallet information, NFT operations, and token analytics.', - preview: '/eliza/logos/ankr.jpg', + preview: '/logos/ankr.jpg', website: 'https://github.com/elizaos-plugins/plugin-ankr', source: 'https://github.com/elizaos-plugins/plugin-ankr', tags: ['plugin'], @@ -1018,7 +1018,7 @@ export const registryUsers: User[] = [ title: 'Arbitrage', description: 'Identifies and executes cryptocurrency arbitrage opportunities across multiple exchanges.', - preview: '/eliza/logos/arbitage.png', + preview: '/logos/arbitage.png', website: 'https://github.com/elizaos-plugins/plugin-arbitrage', source: 'https://github.com/elizaos-plugins/plugin-arbitrage', tags: ['plugin'], @@ -1027,7 +1027,7 @@ export const registryUsers: User[] = [ title: 'Aws S3', description: 'Provides AWS S3 integration for cloud-based file operations and storage management.', - preview: '/eliza/logos/AWS.jpg', + preview: '/logos/AWS.jpg', website: 'https://github.com/elizaos-plugins/plugin-aws-s3', source: 'https://github.com/elizaos-plugins/plugin-aws-s3', tags: ['plugin'], @@ -1036,7 +1036,7 @@ export const registryUsers: User[] = [ title: 'B2', description: 'Enables token transfers on the B2-Network blockchain with support for B2-BTC and ERC20 tokens.', - preview: '/eliza/logos/B2network.jpg', + preview: '/logos/B2network.jpg', website: 'https://github.com/elizaos-plugins/plugin-b2', source: 'https://github.com/elizaos-plugins/plugin-b2', tags: ['plugin'], @@ -1045,7 +1045,7 @@ export const registryUsers: User[] = [ title: 'Birdeye', description: "Offers DeFi and token analytics through Birdeye's API with real-time blockchain data across multiple networks.", - preview: '/eliza/logos/birdeye.jpg', + preview: '/logos/birdeye.jpg', website: 'https://github.com/elizaos-plugins/plugin-birdeye', source: 'https://github.com/elizaos-plugins/plugin-birdeye', tags: ['plugin'], @@ -1054,7 +1054,7 @@ export const registryUsers: User[] = [ title: 'Bittensor', description: "Integrates BitMind's API for accessing AI services on the Bittensor network, especially deepfake detection.", - preview: '/eliza/logos/bittensor.jpg', + preview: '/logos/bittensor.jpg', website: 'https://github.com/elizaos-plugins/plugin-bittensor', source: 'https://github.com/elizaos-plugins/plugin-bittensor', tags: ['plugin'], @@ -1063,7 +1063,7 @@ export const registryUsers: User[] = [ title: 'Bnb', description: 'Enables interactions with BNB Chain ecosystem including BNB Smart Chain, opBNB, and BNB Greenfield networks.', - preview: '/eliza/logos/BNBchain.jpg', + preview: '/logos/BNBchain.jpg', website: 'https://github.com/elizaos-plugins/plugin-bnb', source: 'https://github.com/elizaos-plugins/plugin-bnb', tags: ['plugin'], @@ -1072,7 +1072,7 @@ export const registryUsers: User[] = [ title: 'Bootstrap', description: 'Provides core functionality for ElizaOS agents including conversation management and fact tracking.', - preview: '/eliza/logos/bootstrap.jpg', + preview: '/logos/bootstrap.jpg', website: 'https://github.com/elizaos-plugins/plugin-bootstrap', source: 'https://github.com/elizaos-plugins/plugin-bootstrap', tags: ['plugin'], @@ -1081,7 +1081,7 @@ export const registryUsers: User[] = [ title: 'Browser', description: 'Provides web scraping and browser automation using Playwright with support for multiple browsers and interactions.', - preview: '/eliza/logos/browser.playwright.jpg', + preview: '/logos/browser.playwright.jpg', website: 'https://github.com/elizaos-plugins/plugin-browser', source: 'https://github.com/elizaos-plugins/plugin-browser', tags: ['plugin'], @@ -1090,7 +1090,7 @@ export const registryUsers: User[] = [ title: 'Chainbase', description: 'Bridges on-chain data with AI agents, enabling natural language interactions with blockchain data across networks.', - preview: '/eliza/logos/chainbase.jpg', + preview: '/logos/chainbase.jpg', website: 'https://github.com/elizaos-plugins/plugin-chainbase', source: 'https://github.com/elizaos-plugins/plugin-chainbase', tags: ['plugin'], @@ -1099,7 +1099,7 @@ export const registryUsers: User[] = [ title: 'Cronos', description: 'Extends EVM plugin functionality for Cronos blockchain with native CRO token support and wallet operations.', - preview: '/eliza/logos/cronos.jpg', + preview: '/logos/cronos.jpg', website: 'https://github.com/elizaos-plugins/plugin-cronos', source: 'https://github.com/elizaos-plugins/plugin-cronos', tags: ['plugin'], @@ -1108,7 +1108,7 @@ export const registryUsers: User[] = [ title: 'Desk Exchange', description: 'Integrates with DESK Exchange for perpetual futures trading with support for market and limit orders.', - preview: '/eliza/logos/desk.jpg', + preview: '/logos/desk.jpg', website: 'https://github.com/elizaos-plugins/plugin-desk-exchange', source: 'https://github.com/elizaos-plugins/plugin-desk-exchange', tags: ['plugin'], @@ -1117,7 +1117,7 @@ export const registryUsers: User[] = [ title: 'Devin', description: 'Provides integration with Devin API for automated engineering assistance and session management.', - preview: '/eliza/logos/devin.png', + preview: '/logos/devin.png', website: 'https://github.com/elizaos-plugins/plugin-devin', source: 'https://github.com/elizaos-plugins/plugin-devin', tags: ['plugin'], @@ -1126,7 +1126,7 @@ export const registryUsers: User[] = [ title: 'Dexscreener', description: "Accesses DexScreener's token data for price information and market trends across multiple blockchains.", - preview: '/eliza/logos/dexscreener.jpg', + preview: '/logos/dexscreener.jpg', website: 'https://github.com/elizaos-plugins/plugin-dexscreener', source: 'https://github.com/elizaos-plugins/plugin-dexscreener', tags: ['plugin'], @@ -1135,7 +1135,7 @@ export const registryUsers: User[] = [ title: 'Dkg', description: 'Enables integration with OriginTrail Decentralized Knowledge Graph for enhanced search capabilities.', - preview: '/eliza/logos/OriginTrail.jpg', + preview: '/logos/OriginTrail.jpg', website: 'https://github.com/elizaos-plugins/plugin-dkg', source: 'https://github.com/elizaos-plugins/plugin-dkg', tags: ['plugin'], @@ -1144,7 +1144,7 @@ export const registryUsers: User[] = [ title: 'Email', description: 'Implements email client functionality for sending and receiving emails through SMTP/IMAP services.', - preview: '/eliza/logos/email.png', + preview: '/logos/email.png', website: 'https://github.com/elizaos-plugins/plugin-email', source: 'https://github.com/elizaos-plugins/plugin-email', tags: ['plugin'], @@ -1153,7 +1153,7 @@ export const registryUsers: User[] = [ title: 'Email Automation', description: 'Intelligently detects email-worthy conversations and handles generation/delivery with AI-powered content formatting.', - preview: '/eliza/logos/email.jpg', + preview: '/logos/email.jpg', website: 'https://github.com/elizaos-plugins/plugin-email-automation', source: 'https://github.com/elizaos-plugins/plugin-email-automation', tags: ['plugin'], @@ -1162,7 +1162,7 @@ export const registryUsers: User[] = [ title: 'Ethstorage', description: 'Enables interaction with EthStorage decentralized storage network for data submission and token transfers.', - preview: '/eliza/logos/ETHstorage.jpg', + preview: '/logos/ETHstorage.jpg', website: 'https://github.com/elizaos-plugins/plugin-ethstorage', source: 'https://github.com/elizaos-plugins/plugin-ethstorage', tags: ['plugin'], @@ -1171,7 +1171,7 @@ export const registryUsers: User[] = [ title: 'Football', description: 'Provides live football match data and league standings information through the Football-Data.org API.', - preview: '/eliza/logos/footballDATA.jpg', + preview: '/logos/footballDATA.jpg', website: 'https://github.com/elizaos-plugins/plugin-football', source: 'https://github.com/elizaos-plugins/plugin-football', tags: ['plugin'], @@ -1180,7 +1180,7 @@ export const registryUsers: User[] = [ title: 'Form', description: 'Integrates Form chain capabilities for curves-based token economics with ERC20 conversion and management.', - preview: '/eliza/logos/form.jpg', + preview: '/logos/form.jpg', website: 'https://github.com/elizaos-plugins/plugin-form', source: 'https://github.com/elizaos-plugins/plugin-form', tags: ['plugin'], @@ -1189,7 +1189,7 @@ export const registryUsers: User[] = [ title: 'Gelato', description: 'Enables smart contract interactions via Gelato Relay supporting both ERC2771 and non-ERC2771 calls on EVM chains.', - preview: '/eliza/logos/gelato.jpg', + preview: '/logos/gelato.jpg', website: 'https://github.com/elizaos-plugins/plugin-gelato', source: 'https://github.com/elizaos-plugins/plugin-gelato', tags: ['plugin'], @@ -1198,7 +1198,7 @@ export const registryUsers: User[] = [ title: 'Gitcoin Passport', description: 'Interacts with Gitcoin Passport API for verifying and managing digital identity credentials.', - preview: '/eliza/logos/gitcoin.passport.jpg', + preview: '/logos/gitcoin.passport.jpg', website: 'https://github.com/elizaos-plugins/plugin-gitcoin-passport', source: 'https://github.com/elizaos-plugins/plugin-gitcoin-passport', tags: ['plugin'], @@ -1207,7 +1207,7 @@ export const registryUsers: User[] = [ title: 'Holdstation', description: 'Enables token swapping on Holdstation DEX with support for ZKsync Era and upcoming Berachain.', - preview: '/eliza/logos/holdstation.jpg', + preview: '/logos/holdstation.jpg', website: 'https://github.com/elizaos-plugins/plugin-holdstation', source: 'https://github.com/elizaos-plugins/plugin-holdstation', tags: ['plugin'], @@ -1216,7 +1216,7 @@ export const registryUsers: User[] = [ title: 'Hyperbolic', description: 'Manages GPU instances on the Hyperbolic platform with capabilities for renting and monitoring resources.', - preview: '/eliza/logos/hyperbolic.jpg', + preview: '/logos/hyperbolic.jpg', website: 'https://github.com/elizaos-plugins/plugin-hyperbolic', source: 'https://github.com/elizaos-plugins/plugin-hyperbolic', tags: ['plugin'], @@ -1225,7 +1225,7 @@ export const registryUsers: User[] = [ title: 'Image', description: 'Processes and analyzes images to generate descriptions with support for multiple vision model providers.', - preview: '/eliza/logos/imagegen.jpg', + preview: '/logos/imagegen.jpg', website: 'https://github.com/elizaos-plugins/plugin-image', source: 'https://github.com/elizaos-plugins/plugin-image', tags: ['plugin'], @@ -1233,7 +1233,7 @@ export const registryUsers: User[] = [ { title: 'Imgflip', description: 'Generates memes using the imgflip.com API based on user messages.', - preview: '/eliza/logos/imgFlip.jpg', + preview: '/logos/imgFlip.jpg', website: 'https://github.com/elizaos-plugins/plugin-imgflip', source: 'https://github.com/elizaos-plugins/plugin-imgflip', tags: ['plugin'], @@ -1242,7 +1242,7 @@ export const registryUsers: User[] = [ title: 'Initia', description: 'Enables token transfers on the Initia blockchain with support for INIT token transactions.', - preview: '/eliza/logos/initia.jpg', + preview: '/logos/initia.jpg', website: 'https://github.com/elizaos-plugins/plugin-initia', source: 'https://github.com/elizaos-plugins/plugin-initia', tags: ['plugin'], @@ -1251,7 +1251,7 @@ export const registryUsers: User[] = [ title: 'Injective', description: 'Provides comprehensive interaction with the Injective blockchain through module-based action creation.', - preview: '/eliza/logos/injective.jpg', + preview: '/logos/injective.jpg', website: 'https://github.com/elizaos-plugins/plugin-injective', source: 'https://github.com/elizaos-plugins/plugin-injective', tags: ['plugin'], @@ -1260,7 +1260,7 @@ export const registryUsers: User[] = [ title: 'Iq6900', description: "Provides blockchain inscription functionality through IQ6900's Code-In standard for permanent agent storage.", - preview: '/eliza/logos/IQ6900.jpg', + preview: '/logos/IQ6900.jpg', website: 'https://github.com/elizaos-plugins/plugin-iq6900', source: 'https://github.com/elizaos-plugins/plugin-iq6900', tags: ['plugin'], @@ -1268,7 +1268,7 @@ export const registryUsers: User[] = [ { title: 'Lens Network', description: 'Integrates with Lens protocol for both native and ERC20 tokens.', - preview: '/eliza/logos/lens.jpg', + preview: '/logos/lens.jpg', website: 'https://github.com/elizaos-plugins/plugin-lens-network', source: 'https://github.com/elizaos-plugins/plugin-lens-network', tags: ['plugin'], @@ -1277,7 +1277,7 @@ export const registryUsers: User[] = [ title: 'Lightning', description: 'Enables Lightning Network integration for creating invoices and making off-chain Bitcoin payments.', - preview: '/eliza/logos/lightning.png', + preview: '/logos/lightning.png', website: 'https://github.com/elizaos-plugins/plugin-lightning', source: 'https://github.com/elizaos-plugins/plugin-lightning', tags: ['plugin'], @@ -1286,7 +1286,7 @@ export const registryUsers: User[] = [ title: 'Lit', description: 'Integrates Lit Protocol for secure and decentralized access control and cryptographic operations.', - preview: '/eliza/logos/LitProtocol.jpg', + preview: '/logos/LitProtocol.jpg', website: 'https://github.com/elizaos-plugins/plugin-lit', source: 'https://github.com/elizaos-plugins/plugin-lit', tags: ['plugin'], @@ -1295,7 +1295,7 @@ export const registryUsers: User[] = [ title: 'Llama', description: 'Provides local LLM capabilities using LLaMA models with CPU and GPU support for efficient text generation.', - preview: '/eliza/logos/meta-llama.jpg', + preview: '/logos/meta-llama.jpg', website: 'https://github.com/elizaos-plugins/plugin-llama', source: 'https://github.com/elizaos-plugins/plugin-llama', tags: ['plugin'], @@ -1304,7 +1304,7 @@ export const registryUsers: User[] = [ title: 'Mina', description: 'Enables Mina blockchain interactions for token transfers, wallet management, and balance queries.', - preview: '/eliza/logos/Mina.jpg', + preview: '/logos/Mina.jpg', website: 'https://github.com/elizaos-plugins/plugin-mina', source: 'https://github.com/elizaos-plugins/plugin-mina', tags: ['plugin'], @@ -1313,7 +1313,7 @@ export const registryUsers: User[] = [ title: 'Mind Network', description: 'Integrates with Mind Network Hubs for secure, privacy-preserving voting using Fully Homomorphic Encryption.', - preview: '/eliza/logos/MindNetwork.jpg', + preview: '/logos/MindNetwork.jpg', website: 'https://github.com/elizaos-plugins/plugin-mind-network', source: 'https://github.com/elizaos-plugins/plugin-mind-network', tags: ['plugin'], @@ -1322,7 +1322,7 @@ export const registryUsers: User[] = [ title: 'Moralis', description: 'Fetches real-time DeFi data including trading pairs, statistics, and price history through Moralis APIs.', - preview: '/eliza/logos/moralis.jpg', + preview: '/logos/moralis.jpg', website: 'https://github.com/elizaos-plugins/plugin-moralis', source: 'https://github.com/elizaos-plugins/plugin-moralis', tags: ['plugin'], @@ -1331,7 +1331,7 @@ export const registryUsers: User[] = [ title: 'News', description: 'Fetches and handles real-time news data through NewsAPI integration with search and summary capabilities.', - preview: '/eliza/logos/NewsAPI.jpg', + preview: '/logos/NewsAPI.jpg', website: 'https://github.com/elizaos-plugins/plugin-news', source: 'https://github.com/elizaos-plugins/plugin-news', tags: ['plugin'], @@ -1340,7 +1340,7 @@ export const registryUsers: User[] = [ title: 'Nft Collections', description: 'Integrates NFT data services for comprehensive market analytics and trading with support for 420+ verified collections.', - preview: '/eliza/logos/nftgen.png', + preview: '/logos/nftgen.png', website: 'https://github.com/elizaos-plugins/plugin-nft-collections', source: 'https://github.com/elizaos-plugins/plugin-nft-collections', tags: ['plugin'], @@ -1349,7 +1349,7 @@ export const registryUsers: User[] = [ title: 'Nvidia Nim', description: "Integrates NVIDIA's AI foundation models for content analysis including AI image detection and safety checks.", - preview: '/eliza/logos/nvidia.jpg', + preview: '/logos/nvidia.jpg', website: 'https://github.com/elizaos-plugins/plugin-nvidia-nim', source: 'https://github.com/elizaos-plugins/plugin-nvidia-nim', tags: ['plugin'], @@ -1358,7 +1358,7 @@ export const registryUsers: User[] = [ title: 'Openai', description: "Integrates OpenAI's GPT models for automated text generation with customizable prompts.", - preview: '/eliza/logos/openAI.jpg', + preview: '/logos/openAI.jpg', website: 'https://github.com/elizaos-plugins/plugin-openai', source: 'https://github.com/elizaos-plugins/plugin-openai', tags: ['plugin'], @@ -1366,7 +1366,7 @@ export const registryUsers: User[] = [ { title: 'Pdf', description: 'Provides PDF text extraction and processing capabilities for document analysis.', - preview: '/eliza/logos/PDF.jpg', + preview: '/logos/PDF.jpg', website: 'https://github.com/elizaos-plugins/plugin-pdf', source: 'https://github.com/elizaos-plugins/plugin-pdf', tags: ['plugin'], @@ -1375,7 +1375,7 @@ export const registryUsers: User[] = [ title: 'Pyth Data', description: 'Integrates with Pyth Network for real-time price feeds and data streams across multiple asset classes.', - preview: '/eliza/logos/pyth.jpg', + preview: '/logos/pyth.jpg', website: 'https://github.com/elizaos-plugins/plugin-pyth-data', source: 'https://github.com/elizaos-plugins/plugin-pyth-data', tags: ['plugin'], @@ -1384,7 +1384,7 @@ export const registryUsers: User[] = [ title: 'Quick Intel', description: 'Performs token security audits and market analysis with support for multiple chains and address formats.', - preview: '/eliza/logos/quickintel.jpg', + preview: '/logos/quickintel.jpg', website: 'https://github.com/elizaos-plugins/plugin-quick-intel', source: 'https://github.com/elizaos-plugins/plugin-quick-intel', tags: ['plugin'], @@ -1393,7 +1393,7 @@ export const registryUsers: User[] = [ title: 'Router Nitro', description: 'Enables cross-chain token transfers using Router Nitro bridge with support for multiple blockchains.', - preview: '/eliza/logos/router.jpg', + preview: '/logos/router.jpg', website: 'https://github.com/elizaos-plugins/plugin-router-nitro', source: 'https://github.com/elizaos-plugins/plugin-router-nitro', tags: ['plugin'], @@ -1402,7 +1402,7 @@ export const registryUsers: User[] = [ title: 'Solana Agentkit', description: 'Enables interaction with the Solana blockchain through AgentKit for wallet and transaction management.', - preview: '/eliza/logos/solanaV2.jpg', + preview: '/logos/solanaV2.jpg', website: 'https://github.com/elizaos-plugins/plugin-solana-agentkit', source: 'https://github.com/elizaos-plugins/plugin-solana-agentkit', tags: ['plugin'], @@ -1411,7 +1411,7 @@ export const registryUsers: User[] = [ title: 'Solana V2', description: 'Leverages @solana/web3.js v2 for modern, efficient Solana integrations with liquidity position management.', - preview: '/eliza/logos/solanaV2.jpg', + preview: '/logos/solanaV2.jpg', website: 'https://github.com/elizaos-plugins/plugin-solana-v2', source: 'https://github.com/elizaos-plugins/plugin-solana-v2', tags: ['plugin'], @@ -1420,7 +1420,7 @@ export const registryUsers: User[] = [ title: 'Speech Tts', description: 'Provides text-to-speech transcription services using OpenAI and ElevenLabs technologies.', - preview: '/eliza/logos/TTSelevenlabs.jpg', + preview: '/logos/TTSelevenlabs.jpg', website: 'https://github.com/elizaos-plugins/plugin-speech-tts', source: 'https://github.com/elizaos-plugins/plugin-speech-tts', tags: ['plugin'], @@ -1429,7 +1429,7 @@ export const registryUsers: User[] = [ title: 'Squid Router', description: 'Enables cross-chain token swaps between blockchains using the Squid Router protocol.', - preview: '/eliza/logos/squid.jpg', + preview: '/logos/squid.jpg', website: 'https://github.com/elizaos-plugins/plugin-squid-router', source: 'https://github.com/elizaos-plugins/plugin-squid-router', tags: ['plugin'], @@ -1438,7 +1438,7 @@ export const registryUsers: User[] = [ title: 'Suno', description: "Integrates Suno AI's music generation for creating custom music from text prompts with detailed controls.", - preview: '/eliza/logos/suno.jpg', + preview: '/logos/suno.jpg', website: 'https://github.com/elizaos-plugins/plugin-suno', source: 'https://github.com/elizaos-plugins/plugin-suno', tags: ['plugin'], @@ -1447,7 +1447,7 @@ export const registryUsers: User[] = [ title: 'Tee Verifiable Log', description: 'Implements a verifiable logging system within Trusted Execution Environments for secure, auditable records.', - preview: '/eliza/logos/tee.png', + preview: '/logos/tee.png', website: 'https://github.com/elizaos-plugins/plugin-tee-verifiable-log', source: 'https://github.com/elizaos-plugins/plugin-tee-verifiable-log', tags: ['plugin'], @@ -1456,7 +1456,7 @@ export const registryUsers: User[] = [ title: 'Trikon', description: 'Provides token transfer functionality for Trikon with wallet management on ZKsync Era blockchain.', - preview: '/eliza/logos/trikon.jpg', + preview: '/logos/trikon.jpg', website: 'https://github.com/elizaos-plugins/plugin-trikon', source: 'https://github.com/elizaos-plugins/plugin-trikon', tags: ['plugin'], @@ -1465,7 +1465,7 @@ export const registryUsers: User[] = [ title: 'Trustdb', description: 'Manages trust scores and performance metrics in a secure database for recommender tracking and token analysis.', - preview: '/eliza/logos/trusta.jpg', + preview: '/logos/trusta.jpg', website: 'https://github.com/elizaos-plugins/plugin-trustdb', source: 'https://github.com/elizaos-plugins/plugin-trustdb', tags: ['plugin'], @@ -1474,7 +1474,7 @@ export const registryUsers: User[] = [ title: 'Udio', description: 'Enables AI-powered music generation with capabilities for creating and extending audio from text prompts.', - preview: '/eliza/logos/UDIO.png', + preview: '/logos/UDIO.png', website: 'https://github.com/elizaos-plugins/plugin-udio', source: 'https://github.com/elizaos-plugins/plugin-udio', tags: ['plugin'], @@ -1483,7 +1483,7 @@ export const registryUsers: User[] = [ title: 'Video', description: 'Provides comprehensive video processing with download, format handling, and transcription capabilities.', - preview: '/eliza/logos/video.jpg', + preview: '/logos/video.jpg', website: 'https://github.com/elizaos-plugins/plugin-video', source: 'https://github.com/elizaos-plugins/plugin-video', tags: ['plugin'], @@ -1492,7 +1492,7 @@ export const registryUsers: User[] = [ title: 'Zilliqa', description: 'Integrates Zilliqa blockchain capabilities through the GOAT framework for wallet and transaction functionality.', - preview: '/eliza/logos/zilliqa.jpg', + preview: '/logos/zilliqa.jpg', website: 'https://github.com/elizaos-plugins/plugin-zilliqa', source: 'https://github.com/elizaos-plugins/plugin-zilliqa', tags: ['plugin'], diff --git a/packages/docs/src/pages/index.jsx b/packages/docs/src/pages/index.jsx index 78f76e71635..98d46ac2a8a 100644 --- a/packages/docs/src/pages/index.jsx +++ b/packages/docs/src/pages/index.jsx @@ -1,18 +1,23 @@ +// src/pages/index.jsx import React from 'react'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import HomepageFeatures from '@site/src/components/HomepageFeatures'; import Layout from '@theme/Layout'; - -import styles from './index.module.css'; import HomepageHeader from '../components/HomepageHeader'; +import HomepageFeatures from '../components/HomepageFeatures'; +import DailyNews from '../components/DailyNews'; +import styles from './index.module.css'; export default function Home() { const { siteConfig } = useDocusaurusContext(); return ( - - -
- + +
+ + + +
+ +
); diff --git a/packages/docs/src/pages/index.module.css b/packages/docs/src/pages/index.module.css index 9af8f5975b9..e5332e16004 100644 --- a/packages/docs/src/pages/index.module.css +++ b/packages/docs/src/pages/index.module.css @@ -1,23 +1,40 @@ -/** - * CSS files with the .module.css suffix will be treated as CSS modules - * and scoped locally. - */ +/* src/pages/index.module.css */ +.mainContent { + overflow: hidden; + position: relative; +} + +[data-theme='dark'] .mainContent { + background: radial-gradient(circle at 10% 10%, #1e293b 0%, #111827 90%); +} -.heroBanner { - padding: 4rem 0; - text-align: center; +.newsSectionWrapper { + background: var(--ifm-background-surface-color); + padding: 2rem 0 5rem; position: relative; - overflow: hidden; } -@media screen and (max-width: 1024px) { - .heroBanner { - padding: 2rem; - } +[data-theme='dark'] .newsSectionWrapper { + background: linear-gradient(to bottom, rgba(30, 41, 59, 0.5) 0%, rgba(17, 24, 39, 0.7) 100%); +} + +/* Add a subtle wave divider between sections */ +.newsSectionWrapper::before { + content: ''; + position: absolute; + top: -2px; + left: 0; + width: 100%; + height: 70px; + background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 120' preserveAspectRatio='none'%3E%3Cpath d='M0,0V46.29c47.79,22.2,103.59,32.17,158,28,70.36-5.37,136.33-33.31,206.8-37.5C438.64,32.43,512.34,53.67,583,72.05c69.27,18,138.3,24.88,209.4,13.08,36.15-6,69.85-17.84,104.45-29.34C989.49,25,1113-14.29,1200,52.47V0Z' opacity='.25' fill='%23ffffff'/%3E%3Cpath d='M0,0V15.81C13,36.92,27.64,56.86,47.69,72.05,99.41,111.27,165,111,224.58,91.58c31.15-10.15,60.09-26.07,89.67-39.8,40.92-19,84.73-46,130.83-49.67,36.26-2.85,70.9,9.42,98.6,31.56,31.77,25.39,62.32,62,103.63,73,40.44,10.79,81.35-6.69,119.13-24.28s75.16-39,116.92-43.05c59.73-5.85,113.28,22.88,168.9,38.84,30.2,8.66,59,6.17,87.09-7.5,22.43-10.89,48-26.93,60.65-49.24V0Z' opacity='.5' fill='%23ffffff'/%3E%3Cpath d='M0,0V5.63C149.93,59,314.09,71.32,475.83,42.57c43-7.64,84.23-20.12,127.61-26.46,59-8.63,112.48,12.24,165.56,35.4C827.93,77.22,886,95.24,951.2,90c86.53-7,172.46-45.71,248.8-84.81V0Z' fill='%23ffffff'/%3E%3C/svg%3E") + no-repeat; + background-size: cover; + transform: rotate(180deg); + z-index: 1; } -.buttons { - display: flex; - align-items: center; - justify-content: center; +[data-theme='dark'] .newsSectionWrapper::before { + background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 120' preserveAspectRatio='none'%3E%3Cpath d='M0,0V46.29c47.79,22.2,103.59,32.17,158,28,70.36-5.37,136.33-33.31,206.8-37.5C438.64,32.43,512.34,53.67,583,72.05c69.27,18,138.3,24.88,209.4,13.08,36.15-6,69.85-17.84,104.45-29.34C989.49,25,1113-14.29,1200,52.47V0Z' opacity='.15' fill='%23ffffff'/%3E%3Cpath d='M0,0V15.81C13,36.92,27.64,56.86,47.69,72.05,99.41,111.27,165,111,224.58,91.58c31.15-10.15,60.09-26.07,89.67-39.8,40.92-19,84.73-46,130.83-49.67,36.26-2.85,70.9,9.42,98.6,31.56,31.77,25.39,62.32,62,103.63,73,40.44,10.79,81.35-6.69,119.13-24.28s75.16-39,116.92-43.05c59.73-5.85,113.28,22.88,168.9,38.84,30.2,8.66,59,6.17,87.09-7.5,22.43-10.89,48-26.93,60.65-49.24V0Z' opacity='.3' fill='%23ffffff'/%3E%3Cpath d='M0,0V5.63C149.93,59,314.09,71.32,475.83,42.57c43-7.64,84.23-20.12,127.61-26.46,59-8.63,112.48,12.24,165.56,35.4C827.93,77.22,886,95.24,951.2,90c86.53-7,172.46-45.71,248.8-84.81V0Z' opacity='.15' fill='%23ffffff'/%3E%3C/svg%3E") + no-repeat; + background-size: cover; } diff --git a/packages/docs/static/CNAME b/packages/docs/static/CNAME new file mode 100644 index 00000000000..a0d6512a651 --- /dev/null +++ b/packages/docs/static/CNAME @@ -0,0 +1 @@ +eliza.how diff --git a/packages/docs/static/img/montage-plugins.jpg b/packages/docs/static/img/montage-plugins.jpg new file mode 100644 index 00000000000..796f37db845 Binary files /dev/null and b/packages/docs/static/img/montage-plugins.jpg differ diff --git a/packages/docs/static/llms-full.txt b/packages/docs/static/llms-full.txt new file mode 100644 index 00000000000..59546c859c1 --- /dev/null +++ b/packages/docs/static/llms-full.txt @@ -0,0 +1,4863 @@ +This file is a merged representation of a subset of the codebase, containing specifically included files and files not matching ignore patterns, combined into a single document by Repomix. +The content has been processed where comments have been removed, empty lines have been removed, content has been compressed (code blocks are separated by ⋮---- delimiter). + +# File Summary + +## Purpose +This file contains a packed representation of the entire repository's contents. +It is designed to be easily consumable by AI systems for analysis, code review, +or other automated processes. + +## File Format +The content is organized as follows: +1. This summary section +2. Repository information +3. Directory structure +4. Multiple file entries, each consisting of: + a. A header with the file path (## File: path/to/file) + b. The full contents of the file in a code block + +## Usage Guidelines +- This file should be treated as read-only. Any changes should be made to the + original repository files, not this packed version. +- When processing this file, use the file path to distinguish + between different files in the repository. +- Be aware that this file may contain sensitive information. Handle it with + the same level of security as you would the original repository. +- Pay special attention to the Repository Description. These contain important context and guidelines specific to this project. +- Pay special attention to the Repository Instruction. These contain important context and guidelines specific to this project. + +## Notes +- Some files may have been excluded based on .gitignore rules and Repomix's configuration +- Binary files are not included in this packed representation. Please refer to the Repository Structure section for a complete list of file paths, including binary files +- Only files matching these patterns are included: packages/docs/docs/core/overview.md, packages/docs/docs/quickstart.md, packages/docs/docs/core/actions.md, packages/docs/docs/core/knowledge.md, packages/docs/docs/core/database.md, packages/core/src/types.ts, packages/core/src/runtime.ts, packages/core/src/bootstrap.ts, packages/core/src/database.ts, packages/core/src/actions.ts, packages/core/src/entities.ts, packages/core/src/prompts.ts, packages/core/src/uuid.ts, packages/core/src/logger.ts, packages/core/src/providers/actions.ts, packages/core/src/providers/character.ts, packages/core/src/providers/knowledge.ts, packages/core/src/providers/recentMessages.ts, packages/core/src/providers/relationships.ts, packages/core/src/providers/evaluators.ts, packages/core/src/providers/settings.ts, packages/core/src/actions/reply.ts, packages/core/src/actions/sendMessage.ts, packages/cli/src/index.ts, packages/cli/src/commands/agent.ts, packages/cli/src/commands/start.ts, packages/cli/src/commands/test.ts, packages/cli/src/commands/create.ts, packages/cli/src/commands/env.ts, packages/client/src/lib/api.ts, packages/client/src/types/index.ts, packages/client/src/hooks/use-agent-management.ts, README.md, package.json, .env.example +- Files matching these patterns are excluded: **/*.test.ts, **/__tests__/**, **/node_modules/**, packages/docs/community/**, packages/docs/news/**, packages/plugin-*/**, **/*.ico, **/*.png, **/*.jpg, **/*.svg +- Files matching patterns in .gitignore are excluded +- Files matching default ignore patterns are excluded +- Code comments have been removed from supported file types +- Empty lines have been removed from all files +- Content has been compressed - code blocks are separated by ⋮---- delimiter + +## Additional Info +### User Provided Header +ElizaOS Developer Context - Core technical components and implementation details + +# Directory Structure +``` +packages/ + cli/ + src/ + commands/ + agent.ts + create.ts + env.ts + start.ts + test.ts + index.ts + client/ + src/ + hooks/ + use-agent-management.ts + lib/ + api.ts + types/ + index.ts + core/ + src/ + actions/ + reply.ts + sendMessage.ts + providers/ + actions.ts + character.ts + evaluators.ts + knowledge.ts + recentMessages.ts + relationships.ts + settings.ts + actions.ts + bootstrap.ts + database.ts + entities.ts + logger.ts + prompts.ts + runtime.ts + types.ts + uuid.ts + docs/ + docs/ + core/ + actions.md + database.md + knowledge.md + overview.md + quickstart.md +.env.example +package.json +README.md +``` + +# Files + +## File: packages/cli/src/commands/agent.ts +````typescript +import fs from 'node:fs'; +import path from 'node:path'; +import { handleError } from '@/src/utils/handle-error'; +import { displayAgent } from '@/src/utils/helpers'; +import { logger } from '@elizaos/core'; +import type { Agent } from '@elizaos/core'; +import { Command } from 'commander'; +⋮---- +interface AgentBasic { + id: string; + name: string; + status?: string; + [key: string]: unknown; +} +async function getAgents(): Promise +async function resolveAgentId(idOrNameOrIndex: string): Promise +⋮---- +interface AgentStartPayload { + characterPath?: string; + characterJson?: Record; +} +interface ApiResponse { + success: boolean; + data?: T; + error?: { + code: string; + message: string; + details?: unknown; + }; +} +interface AgentStartResponse { + id: string; + character: Partial; +} +```` + +## File: packages/cli/src/commands/create.ts +````typescript +import { existsSync, readFileSync } from 'node:fs'; +import fs from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { buildProject } from '@/src/utils/build-project'; +import { copyTemplate } from '@/src/utils/copy-template'; +import { handleError } from '@/src/utils/handle-error'; +import { runBunCommand } from '@/src/utils/run-bun'; +import { logger } from '@elizaos/core'; +import { Command } from 'commander'; +import { execa } from 'execa'; +import prompts from 'prompts'; +import colors from 'yoctocolors'; +import { z } from 'zod'; +⋮---- +async function getLocalAvailableDatabases(): Promise +async function installDependencies(targetDir: string) +async function storePostgresUrl(url: string): Promise +function isValidPostgresUrl(url: string): boolean +async function promptAndStorePostgresUrl(): Promise +⋮---- +// Prompt for postgres url with simpler message +⋮---- +// Parse options but use "" as the default for type to force prompting +⋮---- +// Prompt for project type if not specified +⋮---- +// Move up one directory by getting the parent directory path +// First get the directory containing the current .env file +⋮---- +// Then move up one directory from there +```` + +## File: packages/cli/src/commands/env.ts +````typescript +import { existsSync } from 'node:fs'; +import fs from 'node:fs/promises'; +import os from 'node:os'; +import path from 'node:path'; +import { handleError } from '@/src/utils/handle-error'; +import { logger } from '@elizaos/core'; +import { Command } from 'commander'; +import dotenv from 'dotenv'; +import prompts from 'prompts'; +import { rimraf } from 'rimraf'; +import colors from 'yoctocolors'; +⋮---- +async function getCustomEnvPath(): Promise +async function saveCustomEnvPath(customPath: string): Promise +async function getGlobalEnvPath(): Promise +function getLocalEnvPath(): string | null +async function parseEnvFile(filePath: string): Promise> +async function writeEnvFile(filePath: string, envVars: Record): Promise +async function listEnvVars(): Promise +function maskedValue(value: string): string +⋮---- +// If the value looks like a token/API key (longer than 20 chars, no spaces), mask it +⋮---- +/** + * Edit environment variables + * @param scope Whether to edit global or local environment variables + * @returns A boolean indicating whether the user wants to go back to the main menu + */ +async function editEnvVars(scope: 'global' | 'local', fromMainMenu = false): Promise +async function addNewVariable(envPath: string, envVars: Record): Promise +async function resetEnv(): Promise +async function setEnvPath(customPath: string): Promise +⋮---- +async function showMainMenu(): Promise +```` + +## File: packages/cli/src/commands/start.ts +````typescript +import { buildProject } from '@/src/utils/build-project'; +import { + AgentRuntime, + type Character, + type IAgentRuntime, + type Plugin, + logger, + stringToUuid, +} from '@elizaos/core'; +import { Command } from 'commander'; +⋮---- +import fs from 'node:fs'; +import os from 'node:os'; +import path, { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { character as defaultCharacter } from '../characters/eliza'; +import { displayBanner } from '../displayBanner'; +import { AgentServer } from '../server/index'; +import { jsonToCharacter, loadCharacterTryPath } from '../server/loader'; +import { loadConfig, saveConfig } from '../utils/config-manager'; +import { promptForEnvVars } from '../utils/env-prompt'; +import { handleError } from '../utils/handle-error'; +import { installPlugin } from '../utils/install-plugin'; +⋮---- +export const wait = (minTime = 1000, maxTime = 3000) => +export async function promptForProjectPlugins( + project: any, + pluginToLoad?: { name: string } +): Promise +⋮---- +// Prompt for each identified plugin +⋮---- +/** + * Starts an agent with the given character, agent server, initialization function, plugins, and options. + * + * @param character The character object representing the agent. + * @param server The agent server where the agent will be registered. + * @param init Optional initialization function to be called with the agent runtime. + * @param plugins An array of plugins to be used by the agent. + * @param options Additional options for starting the agent, such as data directory and postgres URL. + * @returns A promise that resolves to the agent runtime object. + */ +export async function startAgent( + character: Character, + server: AgentServer, + init?: (runtime: IAgentRuntime) => void, + plugins: Plugin[] = [], + options: { + dataDir?: string; + postgresUrl?: string; + isPluginTestMode?: boolean; + } = {} +): Promise +⋮---- +// For ESM modules we need to use import.meta.url instead of __dirname +⋮---- +// Find package.json relative to the current file +⋮---- +async function stopAgent(runtime: IAgentRuntime, server: AgentServer) +const startAgents = async (options: +⋮---- +// Start agents based on project, plugin, or custom configuration +⋮---- +// Load all project agents, call their init and register their plugins +⋮---- +// Handle both formats: project with agents array and project with single agent +⋮---- +// Prompt for environment variables for all plugins in the project +⋮---- +// wait .5 seconds +⋮---- +export default function registerCommand(cli: Command) +```` + +## File: packages/cli/src/commands/test.ts +````typescript +import { buildProject } from '@/src/utils/build-project'; +import { type IAgentRuntime, type ProjectAgent, logger } from '@elizaos/core'; +import { Command } from 'commander'; +⋮---- +import { existsSync } from 'node:fs'; +⋮---- +import path from 'node:path'; +import { loadProject } from '../project'; +import { AgentServer } from '../server/index'; +import { jsonToCharacter, loadCharacterTryPath } from '../server/loader'; +import { TestRunner } from '../testRunner'; +import { promptForEnvVars } from '../utils/env-prompt'; +import { startAgent } from './start'; +async function checkPortAvailable(port: number): Promise +function checkIfLikelyPluginDir(dir: string): boolean +const runAgentTests = async (options: { + port?: number; + plugin?: string; + skipPlugins?: boolean; + skipProjectTests?: boolean; + skipBuild?: boolean; +}) => +⋮---- +export default function registerCommand(cli: Command) +```` + +## File: packages/cli/src/index.ts +````typescript +import fs from 'node:fs'; +import path from 'node:path'; +import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { logger } from '@elizaos/core'; +import { Command } from 'commander'; +import { agent } from './commands/agent'; +import { create } from './commands/create'; +import { dev } from './commands/dev'; +import { env } from './commands/env'; +import { plugin } from './commands/plugin'; +import { project } from './commands/project'; +import { publish } from './commands/publish'; +import { start } from './commands/start'; +import { teeCommand as tee } from './commands/tee'; +import { test } from './commands/test'; +import { update } from './commands/update'; +import { loadEnvironment } from './utils/get-config'; +import { displayBanner } from './displayBanner'; +⋮---- +async function main() +```` + +## File: packages/client/src/hooks/use-agent-management.ts +````typescript +import type { Agent, UUID } from '@elizaos/core'; +import { useQueryClient } from '@tanstack/react-query'; +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useStartAgent, useStopAgent } from './use-query-hooks'; +import { useToast } from './use-toast'; +export function useAgentManagement() +⋮---- +const startAgent = async (agent: Agent) => +const stopAgent = async (agent: Agent) => +const isAgentStarting = (agentId: UUID | undefined | null) => +const isAgentStopping = (agentId: UUID | undefined | null) => +```` + +## File: packages/client/src/lib/api.ts +````typescript +import type { Agent, Character, UUID, Memory } from '@elizaos/core'; +import { WorldManager } from './world-manager'; +⋮---- +const fetcher = async ({ + url, + method, + body, + headers, +}: { + url: string; + method?: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH'; + body?: object | FormData; + headers?: HeadersInit; +}) => +interface LogEntry { + level: number; + time: number; + msg: string; + [key: string]: string | number | boolean | null | undefined; +} +interface LogResponse { + logs: LogEntry[]; + count: number; + total: number; + level: string; + levels: string[]; +} +interface AgentLog { + id?: string; + type?: string; + timestamp?: number; + message?: string; + details?: string; + roomId?: string; + [key: string]: any; +} +```` + +## File: packages/client/src/types/index.ts +````typescript +export interface IAttachment { + url: string; + contentType: string; + title: string; +} +```` + +## File: packages/core/src/actions/reply.ts +````typescript +import { composePromptFromState, parseJSONObjectFromText } from '../prompts'; +import { + type Action, + type ActionExample, + type Content, + type HandlerCallback, + type IAgentRuntime, + type Memory, + ModelType, + type State, +} from '../types'; +```` + +## File: packages/core/src/actions/sendMessage.ts +````typescript +import { findEntityByName } from '../entities'; +import { logger } from '../logger'; +import { composePromptFromState, parseJSONObjectFromText } from '../prompts'; +import { + type Action, + type ActionExample, + type HandlerCallback, + type IAgentRuntime, + type Memory, + ModelType, + type State, +} from '../types'; +```` + +## File: packages/core/src/providers/actions.ts +````typescript +import { composeActionExamples, formatActionNames, formatActions } from '../actions'; +import { addHeader } from '../prompts'; +import type { Action, IAgentRuntime, Memory, Provider, State } from '../types'; +⋮---- +// Combine all text sections +```` + +## File: packages/core/src/providers/character.ts +````typescript +import { addHeader } from '../prompts'; +import { ChannelType, type IAgentRuntime, type Memory, type Provider, type State } from '../types'; +⋮---- +// System prompt +⋮---- +// Select random topic if available +⋮---- +// Format topics list +⋮---- +// Select random adjective if available +⋮---- +// Format post examples +⋮---- +// Format message examples +⋮---- +// Style directions +⋮---- +// Combine all text sections +```` + +## File: packages/core/src/providers/evaluators.ts +````typescript +import { names, uniqueNamesGenerator } from 'unique-names-generator'; +import { addHeader } from '../prompts'; +import type { ActionExample, State } from '../types'; +import type { Evaluator, IAgentRuntime, Memory, Provider } from '../types'; +export function formatEvaluatorNames(evaluators: Evaluator[]) +export function formatEvaluatorExamples(evaluators: Evaluator[]) +export function formatEvaluators(evaluators: Evaluator[]) +⋮---- +// Combine all text sections +```` + +## File: packages/core/src/providers/knowledge.ts +````typescript +import { addHeader } from '../prompts'; +import type { IAgentRuntime, Memory, Provider } from '../types'; +```` + +## File: packages/core/src/providers/recentMessages.ts +````typescript +import { getEntityDetails } from '../entities'; +import { addHeader, formatMessages, formatPosts } from '../prompts'; +import { + ChannelType, + type Entity, + type IAgentRuntime, + type Memory, + type Provider, + type UUID, +} from '../types'; +const getRecentInteractions = async ( + runtime: IAgentRuntime, + sourceEntityId: UUID, + targetEntityId: UUID, + excludeRoomId: UUID +): Promise => +⋮---- +// Preload all necessary entities for both types of interactions +⋮---- +// Only proceed if there are interactions to process +⋮---- +// Get unique entity IDs that aren't the runtime agent +⋮---- +const getRecentMessageInteractions = async ( + recentInteractionsData: Memory[] +): Promise => +const getRecentPostInteractions = async ( + recentInteractionsData: Memory[], + entities: Entity[] +): Promise => +```` + +## File: packages/core/src/providers/relationships.ts +````typescript +import type { Entity, IAgentRuntime, Memory, Provider, Relationship, UUID } from '../types'; +async function formatRelationships(runtime: IAgentRuntime, relationships: Relationship[]) +⋮---- +// Deduplicate target entity IDs to avoid redundant fetches +⋮---- +// Fetch all required entities in a single batch operation +⋮---- +// Create a lookup map for efficient access +⋮---- +const formatMetadata = (metadata: any) => +// Format relationships using the entity map +```` + +## File: packages/core/src/providers/settings.ts +````typescript +import { logger } from '../logger'; +import { findWorldForOwner } from '../roles'; +import { getWorldSettings } from '../settings'; +import { + ChannelType, + type IAgentRuntime, + type Memory, + type Provider, + type ProviderResult, + type Setting, + type State, + type WorldSettings, +} from '../types'; +const formatSettingValue = (setting: Setting, isOnboarding: boolean): string => +function generateStatusMessage( + runtime: IAgentRuntime, + worldSettings: WorldSettings, + isOnboarding: boolean, + state?: State +): string +⋮---- +// Skip settings that should be hidden based on visibility function +⋮---- +// Count required settings that are not configured +⋮---- +// Generate appropriate message +⋮---- +// Non-onboarding context - list all public settings with values and descriptions +⋮---- +/** + * Creates an settings provider with the given configuration + * Updated to use world metadata instead of cache + */ +⋮---- +// Parallelize the initial database operations to improve performance +// These operations can run simultaneously as they don't depend on each other +⋮---- +// In onboarding mode, use the user's world directly +⋮---- +// Fetch world settings based on the server ID +⋮---- +// For non-onboarding, we need to get the world associated with the room +⋮---- +// Once we have the serverId, get the settings +⋮---- +// If no server found after recovery attempts +```` + +## File: packages/core/src/actions.ts +````typescript +import { names, uniqueNamesGenerator } from 'unique-names-generator'; +import type { Action, ActionExample } from './types'; +export const composeActionExamples = (actionsData: Action[], count: number) => +/** + * Formats the names of the provided actions into a comma-separated string. + * @param actions - An array of `Action` objects from which to extract names. + * @returns A comma-separated string of action names. + */ +export function formatActionNames(actions: Action[]) +export function formatActions(actions: Action[]) +```` + +## File: packages/core/src/bootstrap.ts +````typescript +import type { UUID } from 'node:crypto'; +import fs from 'node:fs'; +import path from 'node:path'; +import { v4 } from 'uuid'; +import { choiceAction } from './actions/choice'; +import { followRoomAction } from './actions/followRoom'; +import { ignoreAction } from './actions/ignore'; +import { muteRoomAction } from './actions/muteRoom'; +import { noneAction } from './actions/none'; +import { replyAction } from './actions/reply'; +import updateRoleAction from './actions/roles'; +import { sendMessageAction } from './actions/sendMessage'; +import updateSettingsAction from './actions/settings'; +import { unfollowRoomAction } from './actions/unfollowRoom'; +import { unmuteRoomAction } from './actions/unmuteRoom'; +import { updateEntityAction } from './actions/updateEntity'; +import { createUniqueUuid } from './entities'; +import { reflectionEvaluator } from './evaluators/reflection'; +import { logger } from './logger'; +import { + composePrompt, + composePromptFromState, + messageHandlerTemplate, + parseJSONObjectFromText, + postCreationTemplate, + shouldRespondTemplate, + truncateToCompleteSentence, +} from './prompts'; +import { actionsProvider } from './providers/actions'; +import { anxietyProvider } from './providers/anxiety'; +import { attachmentsProvider } from './providers/attachments'; +import { capabilitiesProvider } from './providers/capabilities'; +import { characterProvider } from './providers/character'; +import { choiceProvider } from './providers/choice'; +import { entitiesProvider } from './providers/entities'; +import { evaluatorsProvider } from './providers/evaluators'; +import { factsProvider } from './providers/facts'; +import { knowledgeProvider } from './providers/knowledge'; +import { providersProvider } from './providers/providers'; +import { recentMessagesProvider } from './providers/recentMessages'; +import { relationshipsProvider } from './providers/relationships'; +import { roleProvider } from './providers/roles'; +import { settingsProvider } from './providers/settings'; +import { timeProvider } from './providers/time'; +import { ScenarioService } from './services/scenario'; +import { TaskService } from './services/task'; +import { + type ActionEventPayload, + ChannelType, + type Content, + type Entity, + type EntityPayload, + type EvaluatorEventPayload, + EventType, + type HandlerCallback, + type IAgentRuntime, + type InvokePayload, + type Media, + type Memory, + type MessagePayload, + ModelType, + type MessageReceivedHandlerParams, + type Plugin, + type WorldPayload, + asUUID, +} from './types'; +type MediaData = { + data: Buffer; + mediaType: string; +}; +⋮---- +export async function fetchMediaData(attachments: Media[]): Promise +const messageReceivedHandler = async ({ + runtime, + message, + callback, +}: MessageReceivedHandlerParams): Promise => +const reactionReceivedHandler = async ({ + runtime, + message, +}: { + runtime: IAgentRuntime; + message: Memory; +}) => +const postGeneratedHandler = async ({ + runtime, + callback, + worldId, + userId, + roomId, +}: InvokePayload) => +⋮---- +function cleanupTweetText(text: string): string +⋮---- +// Fix newlines +⋮---- +// Truncate to Twitter's character limit (280) +⋮---- +// Cleanup the tweet text +⋮---- +// Prepare media if included +// const mediaData: MediaData[] = []; +// if (jsonResponse.imagePrompt) { +// const images = await runtime.useModel(ModelType.IMAGE, { +// prompt: jsonResponse.imagePrompt, +// output: "no-schema", +⋮---- +const syncSingleUser = async ( + entityId: UUID, + runtime: IAgentRuntime, + serverId: string, + channelId: string, + type: ChannelType, + source: string +) => +const handleServerSync = async ( +```` + +## File: packages/core/src/database.ts +````typescript +import type { + Agent, + Component, + Entity, + IDatabaseAdapter, + Log, + Memory, + Participant, + Relationship, + Room, + Task, + UUID, + World, + MemoryMetadata, +} from './types'; +export abstract class DatabaseAdapter implements IDatabaseAdapter +⋮---- +abstract init(): Promise; +abstract close(): Promise; +abstract getEntityById(entityId: UUID): Promise; +abstract getEntitiesForRoom(roomId: UUID, includeComponents?: boolean): Promise; +abstract createEntity(entity: Entity): Promise; +abstract updateEntity(entity: Entity): Promise; +abstract getComponent( + entityId: UUID, + type: string, + worldId?: UUID, + sourceEntityId?: UUID + ): Promise; +abstract getComponents( + entityId: UUID, + worldId?: UUID, + sourceEntityId?: UUID + ): Promise; +abstract createComponent(component: Component): Promise; +abstract updateComponent(component: Component): Promise; +abstract deleteComponent(componentId: UUID): Promise; +abstract getMemories(params: { + entityId?: UUID; + agentId?: UUID; + roomId?: UUID; + count?: number; + unique?: boolean; + tableName: string; + start?: number; + end?: number; + }): Promise; +abstract getMemoriesByRoomIds(params: { + roomIds: UUID[]; + tableName: string; + limit?: number; + }): Promise; +abstract getMemoryById(id: UUID): Promise; +abstract getMemoriesByIds(memoryIds: UUID[], tableName?: string): Promise; +abstract getCachedEmbeddings( +abstract log(params: { + body: { [key: string]: unknown }; + entityId: UUID; + roomId: UUID; + type: string; + }): Promise; +abstract getLogs(params: { + entityId: UUID; + roomId?: UUID; + type?: string; + count?: number; + offset?: number; + }): Promise; +abstract deleteLog(logId: UUID): Promise; +abstract searchMemories(params: { + tableName: string; + roomId: UUID; + embedding: number[]; + match_threshold: number; + count: number; + unique: boolean; + }): Promise; +abstract createMemory(memory: Memory, tableName: string, unique?: boolean): Promise; +abstract updateMemory( + memory: Partial & { id: UUID; metadata?: MemoryMetadata } + ): Promise; +abstract deleteMemory(memoryId: UUID): Promise; +abstract deleteAllMemories(roomId: UUID, tableName: string): Promise; +abstract countMemories(roomId: UUID, unique?: boolean, tableName?: string): Promise; +abstract getWorld(id: UUID): Promise; +abstract getAllWorlds(): Promise; +abstract createWorld(world: World): Promise; +abstract updateWorld(world: World): Promise; +abstract removeWorld(id: UUID): Promise; +abstract getRoom(roomId: UUID): Promise; +abstract getRooms(worldId: UUID): Promise; +abstract createRoom( +abstract updateRoom(room: Room): Promise; +abstract deleteRoom(roomId: UUID): Promise; +abstract getRoomsForParticipant(entityId: UUID): Promise; +abstract getRoomsForParticipants(userIds: UUID[]): Promise; +abstract addParticipant(entityId: UUID, roomId: UUID): Promise; +abstract removeParticipant(entityId: UUID, roomId: UUID): Promise; +abstract getParticipantsForEntity(entityId: UUID): Promise; +abstract getParticipantsForRoom(roomId: UUID): Promise; +abstract getParticipantUserState( + roomId: UUID, + entityId: UUID + ): Promise<'FOLLOWED' | 'MUTED' | null>; +abstract setParticipantUserState( + roomId: UUID, + entityId: UUID, + state: 'FOLLOWED' | 'MUTED' | null + ): Promise; +abstract createRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + tags?: string[]; + metadata?: Record; + }): Promise; +abstract getRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + }): Promise; +abstract getRelationships(params: +abstract updateRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + tags?: string[]; + metadata?: Record; + }): Promise; +abstract getAgent(agentId: UUID): Promise; +abstract getAgents(): Promise; +abstract createAgent(agent: Partial): Promise; +abstract updateAgent(agentId: UUID, agent: Partial): Promise; +abstract deleteAgent(agentId: UUID): Promise; +abstract ensureAgentExists(agent: Partial): Promise; +abstract ensureEmbeddingDimension(dimension: number): Promise; +abstract getCache(key: string): Promise; +abstract setCache(key: string, value: T): Promise; +abstract deleteCache(key: string): Promise; +abstract createTask(task: Task): Promise; +abstract getTasks(params: +abstract getTask(id: UUID): Promise; +abstract getTasksByName(name: string): Promise; +abstract updateTask(id: UUID, task: Partial): Promise; +abstract deleteTask(id: UUID): Promise; +```` + +## File: packages/core/src/entities.ts +````typescript +import { logger, stringToUuid } from './index'; +import { composePrompt, parseJSONObjectFromText } from './prompts'; +import { + type Entity, + type IAgentRuntime, + type Memory, + ModelType, + type Relationship, + type State, + type UUID, +} from './types'; +⋮---- +async function getRecentInteractions( + runtime: IAgentRuntime, + sourceEntityId: UUID, + candidateEntities: Entity[], + roomId: UUID, + relationships: Relationship[] +): Promise< +export async function findEntityByName( + runtime: IAgentRuntime, + message: Memory, + state: State +): Promise +export const createUniqueUuid = (runtime, baseUserId: UUID | string): UUID => +export async function getEntityDetails({ + runtime, + roomId, +}: { + runtime: IAgentRuntime; + roomId: UUID; +}) +export function formatEntities( +```` + +## File: packages/core/src/logger.ts +````typescript +import pino, { type LogFn, type DestinationStream } from 'pino'; +function parseBooleanFromText(value: string | undefined | null): boolean +interface LogEntry { + time?: number; + [key: string]: unknown; +} +class InMemoryDestination implements DestinationStream +⋮---- +constructor(stream: DestinationStream | null) +write(data: string | LogEntry): void +⋮---- +// Filter only service/agent registration logs, not all agent logs +⋮---- +recentLogs(): LogEntry[] +clear(): void +⋮---- +const createStream = async () => +⋮---- +logMethod(inputArgs: [string | Record, ...unknown[]], method: LogFn): void +⋮---- +interface LoggerWithClear extends pino.Logger { + clear: () => void; +} +```` + +## File: packages/core/src/prompts.ts +````typescript +import handlebars from 'handlebars'; +import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter'; +import { names, uniqueNamesGenerator } from 'unique-names-generator'; +import logger from './logger'; +import type { Content, Entity, IAgentRuntime, Memory, State, TemplateType } from './types'; +import { ModelType } from './types'; +export const composePrompt = ({ + state, + template, +}: { + state: { [key: string]: string }; + template: TemplateType; +}) => +export const composePromptFromState = ({ + state, + template, +}: { + state: State; + template: TemplateType; +}) => +export const addHeader = (header: string, body: string) => +/** + * Generates a string with random user names populated in a template. + * + * This function generates random user names and populates placeholders + * in the provided template with these names. Placeholders in the template should follow the format `{{userX}}` + * where `X` is the position of the user (e.g., `{{name1}}`, `{{name2}}`). + * + * @param {string} template - The template string containing placeholders for random user names. + * @param {number} length - The number of random user names to generate. + * @returns {string} The template string with placeholders replaced by random user names. + * + * @example + * // Given a template and a length + * const template = "Hello, {{name1}}! Meet {{name2}} and {{name3}}."; + * const length = 3; + * + * // Composing the random user string will result in: + * // "Hello, John! Meet Alice and Bob." + * const result = composeRandomUser(template, length); + */ +export const composeRandomUser = (template: string, length: number) => +export const formatPosts = ({ + messages, + entities, + conversationHeader = true, +}: { + messages: Memory[]; + entities: Entity[]; + conversationHeader?: boolean; +}) => +⋮---- +// Group messages by roomId +⋮---- +// Sort messages within each roomId by createdAt (oldest to newest) +⋮---- +// Sort rooms by the newest message's createdAt +⋮---- +/** + * Format messages into a string + * @param {Object} params - The formatting parameters + * @param {Memory[]} params.messages - List of messages to format + * @param {Entity[]} params.entities - List of entities for name resolution + * @returns {string} Formatted message string with timestamps and user information + */ +export const formatMessages = ({ + messages, + entities, +}: { + messages: Memory[]; + entities: Entity[]; +}) => +⋮---- +// for each thought, action, text or attachment, add a new line, with text first, then thought, then action, then attachment +⋮---- +export const formatTimestamp = (messageDate: number) => +⋮---- +/** + * Parses a string to determine its boolean equivalent. + * + * Recognized affirmative values: "YES", "Y", "TRUE", "T", "1", "ON", "ENABLE" + * Recognized negative values: "NO", "N", "FALSE", "F", "0", "OFF", "DISABLE" + * + * @param {string | undefined | null} value - The input text to parse + * @returns {boolean} - Returns `true` for affirmative inputs, `false` for negative or unrecognized inputs + */ +export function parseBooleanFromText(value: string | undefined | null): boolean +⋮---- +export function parseJsonArrayFromText(text: string) +⋮---- +// Only replace quotes that are actually being used for string delimitation +⋮---- +export function parseJSONObjectFromText(text: string): Record | null +export function extractAttributes( + response: string, + attributesToExtract?: string[] +): +export const normalizeJsonString = (str: string) => +⋮---- +// "key": someWord → "key": "someWord" +⋮---- +// Replace adjacent quote pairs with a single double quote +⋮---- +/** + * Cleans a JSON-like response string by removing unnecessary markers, line breaks, and extra whitespace. + * This is useful for handling improperly formatted JSON responses from external sources. + * + * @param response - The raw JSON-like string response to clean. + * @returns The cleaned string, ready for parsing or further processing. + */ +export function cleanJsonResponse(response: string): string +⋮---- +.replace(/```json\s*/g, '') // Remove ```json +.replace(/```\s*/g, '') // Remove any remaining ``` +.replace(/(\r\n|\n|\r)/g, '') // Remove line breaks +⋮---- +type ActionResponse = { + like: boolean; + retweet: boolean; + quote?: boolean; + reply?: boolean; +}; +export const parseActionResponseFromText = (text: string): +⋮---- +// Regex patterns +⋮---- +// Check with regex +⋮---- +// Also do line by line parsing as backup +⋮---- +export function truncateToCompleteSentence(text: string, maxLength: number): string +⋮---- +export async function splitChunks(content: string, chunkSize = 512, bleed = 20): Promise +export async function trimTokens(prompt: string, maxTokens: number, runtime: IAgentRuntime) +```` + +## File: packages/core/src/runtime.ts +````typescript +import { v4 as uuidv4 } from 'uuid'; +import { bootstrapPlugin } from './bootstrap'; +import { createUniqueUuid } from './entities'; +import { handlePluginImporting } from './index'; +import logger from './logger'; +import { splitChunks } from './prompts'; +import { ChannelType, MemoryType, ModelType } from './types'; +import type { + Action, + Agent, + Character, + Component, + Entity, + Evaluator, + HandlerCallback, + IAgentRuntime, + IDatabaseAdapter, + KnowledgeItem, + Log, + Memory, + MemoryMetadata, + ModelParamsMap, + ModelResultMap, + ModelTypeName, + Participant, + Plugin, + Provider, + Relationship, + Room, + Route, + Service, + ServiceTypeName, + State, + Task, + TaskWorker, + UUID, + World, +} from './types'; +import { stringToUuid } from './uuid'; +import fs from 'node:fs'; +import path from 'node:path'; +interface Settings { + [key: string]: string | undefined; +} +interface NamespacedSettings { + [namespace: string]: Settings; +} +⋮---- +export function loadEnvConfig(): Settings +⋮---- +function findNearestEnvFile(startDir = process.cwd()) +⋮---- +function parseNamespacedSettings(env: Settings): NamespacedSettings +export class Semaphore +⋮---- +constructor(count: number) +async acquire(): Promise +release(): void +⋮---- +export class AgentRuntime implements IAgentRuntime +⋮---- +constructor(opts: { + conversationLength?: number; + agentId?: UUID; + character?: Character; + plugins?: Plugin[]; + fetch?: typeof fetch; + adapter?: IDatabaseAdapter; +events?: +async registerPlugin(plugin: Plugin): Promise +getAllServices(): Map +async stop() +async initialize() +private async handleProcessingError(error: any, context: string) +private async checkExistingKnowledge(knowledgeId: UUID): Promise +async getKnowledge(message: Memory): Promise +async addKnowledge( + item: KnowledgeItem, + options = { + targetTokens: 3000, + overlap: 200, + modelContextSize: 4096, + } +) +async processCharacterKnowledge(items: string[]) +setSetting(key: string, value: string | boolean | null | any, secret = false) +getSetting(key: string): string | boolean | null | any +/** + * Get the number of messages that are kept in the conversation buffer. + * @returns The number of recent messages to be kept in memory. + */ +getConversationLength() +registerDatabaseAdapter(adapter: IDatabaseAdapter) +/** + * Register a provider for the agent to use. + * @param provider The provider to register. + */ +registerProvider(provider: Provider) +/** + * Register an action for the agent to perform. + * @param action The action to register. + */ +registerAction(action: Action) +⋮---- +// if an action with the same name already exists, throw a warning and don't add the new action +⋮---- +/** + * Register an evaluator to assess and guide the agent's responses. + * @param evaluator The evaluator to register. + */ +registerEvaluator(evaluator: Evaluator) +/** + * Register a context provider to provide context for message generation. + * @param provider The context provider to register. + */ +registerContextProvider(provider: Provider) +/** + * Process the actions of a message. + * @param message The message to process. + * @param responses The array of response memories to process actions from. + * @param state Optional state object for the action processing. + * @param callback Optional callback handler for action results. + */ +async processActions( + message: Memory, + responses: Memory[], + state?: State, + callback?: HandlerCallback +): Promise +⋮---- +function normalizeAction(action: string) +⋮---- +normalizeAction(a.name).includes(normalizedResponseAction) || // the || is kind of a fuzzy match +normalizedResponseAction.includes(normalizeAction(a.name)) // +⋮---- +// log to database +⋮---- +/** + * Evaluate the message and state using the registered evaluators. + * @param message The message to evaluate. + * @param state The state of the agent. + * @param didRespond Whether the agent responded to the message.~ + * @param callback The handler callback + * @returns The results of the evaluation. + */ +async evaluate( + message: Memory, + state: State, + didRespond?: boolean, + callback?: HandlerCallback, + responses?: Memory[] +) +⋮---- +// get the evaluators that were chosen by the response handler +⋮---- +// log to database +⋮---- +async ensureConnection({ + entityId, + roomId, + userName, + name, + source, + type, + channelId, + serverId, + worldId, + }: { + entityId: UUID; + roomId: UUID; + userName?: string; + name?: string; + source?: string; + type?: ChannelType; + channelId?: string; + serverId?: string; + worldId?: UUID; +}) +⋮---- +// Step 1: Handle entity creation/update with proper error handling +⋮---- +// First check if the entity exists +⋮---- +// Try to create the entity +⋮---- +// If we get a duplicate key error, the entity exists in the database but isn't +// associated with this agent - this is expected in multi-agent scenarios +⋮---- +// For any other errors, re-throw +⋮---- +// Entity exists for this agent, update if needed +⋮---- +// Step 2: Ensure world exists +⋮---- +// Step 3: Ensure room exists +⋮---- +// Step 4: Add participants to the room +// For the user entity, we'll try even if we couldn't retrieve it +⋮---- +// If the normal flow fails because the entity isn't found, +// try direct participant addition as a clean fallback +⋮---- +async ensureParticipantInRoom(entityId: UUID, roomId: UUID) +async removeParticipant(entityId: UUID, roomId: UUID): Promise +async getParticipantsForEntity(entityId: UUID): Promise +async getParticipantsForRoom(roomId: UUID): Promise +async addParticipant(entityId: UUID, roomId: UUID): Promise +async ensureWorldExists( +async ensureRoomExists( +async composeState( + message: Memory, + filterList: string[] | null = null, + includeList: string[] | null = null +): Promise +⋮---- +// Get existing provider names from cache (if any) +⋮---- +// Step 1: Determine base set of providers to fetch +⋮---- +// If filter list provided, start with just those providers +⋮---- +// Otherwise, start with all non-private, non-dynamic providers that aren't cached +⋮---- +// Prepare final values +⋮---- +// Safely merge all provider values +⋮---- +getService(service: ServiceTypeName): T | null +async registerService(service: typeof Service): Promise +registerModel(modelType: ModelTypeName, handler: (params: any) => Promise) +getModel( + modelType: ModelTypeName +): ((runtime: IAgentRuntime, params: any) => Promise) | undefined +async useModel( + modelType: T, + params: Omit | any +): Promise +registerEvent(event: string, handler: (params: any) => Promise) +getEvent(event: string): ((params: any) => Promise)[] | undefined +async emitEvent(event: string | string[], params: any) +async ensureEmbeddingDimension() +registerTaskWorker(taskHandler: TaskWorker): void +getTaskWorker(name: string): TaskWorker | undefined +get db(): any +async init(): Promise +async close(): Promise +async getAgent(agentId: UUID): Promise +async getAgents(): Promise +async createAgent(agent: Partial): Promise +async updateAgent(agentId: UUID, agent: Partial): Promise +async deleteAgent(agentId: UUID): Promise +async ensureAgentExists(agent: Partial): Promise +async getEntityById(entityId: UUID): Promise +async getEntitiesForRoom(roomId: UUID, includeComponents?: boolean): Promise +async createEntity(entity: Entity): Promise +async updateEntity(entity: Entity): Promise +async getComponent( + entityId: UUID, + type: string, + worldId?: UUID, + sourceEntityId?: UUID +): Promise +async getComponents(entityId: UUID, worldId?: UUID, sourceEntityId?: UUID): Promise +async createComponent(component: Component): Promise +async updateComponent(component: Component): Promise +async deleteComponent(componentId: UUID): Promise +async addEmbeddingToMemory(memory: Memory): Promise +async getMemories(params: { + entityId?: UUID; + agentId?: UUID; + roomId?: UUID; + count?: number; + unique?: boolean; + tableName: string; + start?: number; + end?: number; +}): Promise +async getMemoryById(id: UUID): Promise +async getMemoriesByIds(ids: UUID[], tableName?: string): Promise +async getMemoriesByRoomIds(params: { + tableName: string; + roomIds: UUID[]; + limit?: number; +}): Promise +async getCachedEmbeddings(params: { + query_table_name: string; + query_threshold: number; + query_input: string; + query_field_name: string; + query_field_sub_name: string; + query_match_count: number; +}): Promise< +async log(params: { + body: { [key: string]: unknown }; + entityId: UUID; + roomId: UUID; + type: string; +}): Promise +async searchMemories(params: { + embedding: number[]; + match_threshold?: number; + count?: number; + roomId?: UUID; + unique?: boolean; + tableName: string; +}): Promise +async createMemory(memory: Memory, tableName: string, unique?: boolean): Promise +async updateMemory( + memory: Partial & { id: UUID; metadata?: MemoryMetadata } +): Promise +async deleteMemory(memoryId: UUID): Promise +async deleteAllMemories(roomId: UUID, tableName: string): Promise +async countMemories(roomId: UUID, unique?: boolean, tableName?: string): Promise +async getLogs(params: { + entityId: UUID; + roomId?: UUID; + type?: string; + count?: number; + offset?: number; +}): Promise +async deleteLog(logId: UUID): Promise +async createWorld(world: World): Promise +async getWorld(id: UUID): Promise +async getAllWorlds(): Promise +async updateWorld(world: World): Promise +async getRoom(roomId: UUID): Promise +async createRoom( +async deleteRoom(roomId: UUID): Promise +async updateRoom(room: Room): Promise +async getRoomsForParticipant(entityId: UUID): Promise +async getRoomsForParticipants(userIds: UUID[]): Promise +async getRooms(worldId: UUID): Promise +async getParticipantUserState( + roomId: UUID, + entityId: UUID +): Promise<'FOLLOWED' | 'MUTED' | null> +async setParticipantUserState( + roomId: UUID, + entityId: UUID, + state: 'FOLLOWED' | 'MUTED' | null +): Promise +async createRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + tags?: string[]; + metadata?: { [key: string]: any }; +}): Promise +async updateRelationship(relationship: Relationship): Promise +async getRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; +}): Promise +async getRelationships(params: +async getCache(key: string): Promise +async setCache(key: string, value: T): Promise +async deleteCache(key: string): Promise +async createTask(task: Task): Promise +async getTasks(params: +async getTask(id: UUID): Promise +async getTasksByName(name: string): Promise +async updateTask(id: UUID, task: Partial): Promise +async deleteTask(id: UUID): Promise +on(event: string, callback: (data: any) => void): void +off(event: string, callback: (data: any) => void): void +emit(event: string, data: any): void +```` + +## File: packages/core/src/types.ts +````typescript +import type { Readable } from 'node:stream'; +export type UUID = `${string}-${string}-${string}-${string}-${string}`; +export function asUUID(id: string): UUID +export interface Content { + thought?: string; + text?: string; + actions?: string[]; + providers?: string[]; + source?: string; + url?: string; + inReplyTo?: UUID; + attachments?: Media[]; + [key: string]: unknown; +} +export interface ActionExample { + name: string; + content: Content; +} +export type ModelTypeName = (typeof ModelType)[keyof typeof ModelType] | string; +⋮---- +export type ServiceTypeName = (typeof ServiceType)[keyof typeof ServiceType]; +⋮---- +export interface State { + [key: string]: any; + values: { + [key: string]: any; + }; + data: { + [key: string]: any; + }; + text: string; +} +export type MemoryTypeAlias = string; +export enum MemoryType { + DOCUMENT = 'document', + FRAGMENT = 'fragment', + MESSAGE = 'message', + DESCRIPTION = 'description', + CUSTOM = 'custom', +} +export type MemoryScope = 'shared' | 'private' | 'room'; +export interface BaseMetadata { + type: MemoryTypeAlias; + source?: string; + sourceId?: UUID; + scope?: MemoryScope; + timestamp?: number; + tags?: string[]; +} +export interface DocumentMetadata extends BaseMetadata { + type: MemoryType.DOCUMENT; +} +export interface FragmentMetadata extends BaseMetadata { + type: MemoryType.FRAGMENT; + documentId: UUID; + position: number; +} +export interface MessageMetadata extends BaseMetadata { + type: MemoryType.MESSAGE; +} +export interface DescriptionMetadata extends BaseMetadata { + type: MemoryType.DESCRIPTION; +} +export interface CustomMetadata extends BaseMetadata { + [key: string]: unknown; +} +export type MemoryMetadata = + | DocumentMetadata + | FragmentMetadata + | MessageMetadata + | DescriptionMetadata + | CustomMetadata; +export interface Memory { + id?: UUID; + entityId: UUID; + agentId?: UUID; + createdAt?: number; + content: Content; + embedding?: number[]; + roomId: UUID; + unique?: boolean; + similarity?: number; + metadata?: MemoryMetadata; +} +export interface Log { + id?: UUID; + entityId: UUID; + roomId?: UUID; + body: { [key: string]: unknown }; + type: string; + createdAt: Date; +} +export interface MessageExample { + name: string; + content: Content; +} +export type Handler = ( + runtime: IAgentRuntime, + message: Memory, + state?: State, + options?: { [key: string]: unknown }, + callback?: HandlerCallback, + responses?: Memory[] +) => Promise; +export type HandlerCallback = (response: Content, files?: any) => Promise; +export type Validator = ( + runtime: IAgentRuntime, + message: Memory, + state?: State +) => Promise; +export interface Action { + similes?: string[]; + description: string; + examples?: ActionExample[][]; + handler: Handler; + name: string; + validate: Validator; +} +export interface EvaluationExample { + prompt: string; + messages: Array; + outcome: string; +} +export interface Evaluator { + alwaysRun?: boolean; + description: string; + similes?: string[]; + examples: EvaluationExample[]; + handler: Handler; + name: string; + validate: Validator; +} +export interface ProviderResult { + values?: { + [key: string]: any; + }; + data?: { + [key: string]: any; + }; + text?: string; +} +export interface Provider { + name: string; + description?: string; + dynamic?: boolean; + position?: number; + private?: boolean; + get: (runtime: IAgentRuntime, message: Memory, state: State) => Promise; +} +export interface Relationship { + id: UUID; + sourceEntityId: UUID; + targetEntityId: UUID; + agentId: UUID; + tags: string[]; + metadata: { + [key: string]: any; + }; + createdAt?: string; +} +export interface Component { + id: UUID; + entityId: UUID; + agentId: UUID; + roomId: UUID; + worldId: UUID; + sourceEntityId: UUID; + type: string; + data: { + [key: string]: any; + }; +} +export interface Entity { + id?: UUID; + names: string[]; + metadata?: { [key: string]: any }; + agentId: UUID; + components?: Component[]; +} +export type World = { + id: UUID; + name?: string; + agentId: UUID; + serverId: string; + metadata?: { + ownership?: { + ownerId: string; + }; + roles?: { + [entityId: UUID]: Role; + }; + [key: string]: unknown; + }; +}; +export type Room = { + id: UUID; + name?: string; + agentId?: UUID; + source: string; + type: ChannelType; + channelId?: string; + serverId?: string; + worldId?: UUID; + metadata?: Record; +}; +export interface Participant { + id: UUID; + entity: Entity; +} +export type Media = { + id: string; + url: string; + title: string; + source: string; + description: string; + text: string; + contentType?: string; +}; +export enum ChannelType { + SELF = 'SELF', + DM = 'dm', + GROUP = 'group', + VOICE_DM = 'VOICE_DM', + VOICE_GROUP = 'VOICE_GROUP', + FEED = 'FEED', + THREAD = 'THREAD', + WORLD = 'WORLD', + FORUM = 'FORUM', + API = 'API', +} +export abstract class Service +⋮---- +constructor(runtime?: IAgentRuntime) +abstract stop(): Promise; +⋮---- +static async start(_runtime: IAgentRuntime): Promise +static async stop(_runtime: IAgentRuntime): Promise +⋮---- +export type Route = { + type: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'STATIC'; + path: string; + filePath?: string; + handler?: (req: any, res: any, runtime: IAgentRuntime) => Promise; +}; +export interface Plugin { + name: string; + description: string; + init?: (config: Record, runtime: IAgentRuntime) => Promise; + config?: { [key: string]: any }; + services?: (typeof Service)[]; + componentTypes?: { + name: string; + schema: Record; + validator?: (data: any) => boolean; + }[]; + actions?: Action[]; + providers?: Provider[]; + evaluators?: Evaluator[]; + adapter?: IDatabaseAdapter; + models?: { + [key: string]: (...args: any[]) => Promise; + }; + events?: { + [K in keyof EventPayloadMap]?: EventHandler[]; + } & { + [key: string]: ((params: EventPayload) => Promise)[]; + }; + routes?: Route[]; + tests?: TestSuite[]; +} +export interface ProjectAgent { + character: Character; + init?: (runtime: IAgentRuntime) => Promise; + plugins?: Plugin[]; + tests?: TestSuite | TestSuite[]; +} +export interface Project { + agents: ProjectAgent[]; +} +export type TemplateType = + | string + | ((options: { state: State | { [key: string]: string } }) => string); +export interface Character { + id?: UUID; + name: string; + username?: string; + system?: string; + templates?: { + [key: string]: TemplateType; + }; + bio: string | string[]; + messageExamples?: MessageExample[][]; + postExamples?: string[]; + topics?: string[]; + adjectives?: string[]; + knowledge?: (string | { path: string; shared?: boolean })[]; + plugins?: string[]; + settings?: { + [key: string]: any | string | boolean | number; + }; + secrets?: { + [key: string]: string | boolean | number; + }; + style?: { + all?: string[]; + chat?: string[]; + post?: string[]; + }; +} +export enum AgentStatus { + ACTIVE = 'active', + INACTIVE = 'inactive', +} +export interface Agent extends Character { + enabled?: boolean; + status?: AgentStatus; + createdAt: number; + updatedAt: number; +} +export interface IDatabaseAdapter { + db: any; + init(): Promise; + close(): Promise; + getAgent(agentId: UUID): Promise; + getAgents(): Promise; + createAgent(agent: Partial): Promise; + updateAgent(agentId: UUID, agent: Partial): Promise; + deleteAgent(agentId: UUID): Promise; + ensureAgentExists(agent: Partial): Promise; + ensureEmbeddingDimension(dimension: number): Promise; + getEntityById(entityId: UUID): Promise; + getEntitiesForRoom(roomId: UUID, includeComponents?: boolean): Promise; + createEntity(entity: Entity): Promise; + updateEntity(entity: Entity): Promise; + getComponent( + entityId: UUID, + type: string, + worldId?: UUID, + sourceEntityId?: UUID + ): Promise; + getComponents(entityId: UUID, worldId?: UUID, sourceEntityId?: UUID): Promise; + createComponent(component: Component): Promise; + updateComponent(component: Component): Promise; + deleteComponent(componentId: UUID): Promise; + getMemories(params: { + entityId?: UUID; + agentId?: UUID; + roomId?: UUID; + count?: number; + unique?: boolean; + tableName: string; + start?: number; + end?: number; + }): Promise; + getMemoryById(id: UUID): Promise; + getMemoriesByIds(ids: UUID[], tableName?: string): Promise; + getMemoriesByRoomIds(params: { + tableName: string; + roomIds: UUID[]; + limit?: number; + }): Promise; + getCachedEmbeddings(params: { + query_table_name: string; + query_threshold: number; + query_input: string; + query_field_name: string; + query_field_sub_name: string; + query_match_count: number; + }): Promise<{ embedding: number[]; levenshtein_score: number }[]>; + log(params: { + body: { [key: string]: unknown }; + entityId: UUID; + roomId: UUID; + type: string; + }): Promise; + getLogs(params: { + entityId: UUID; + roomId?: UUID; + type?: string; + count?: number; + offset?: number; + }): Promise; + deleteLog(logId: UUID): Promise; + searchMemories(params: { + embedding: number[]; + match_threshold?: number; + count?: number; + roomId?: UUID; + unique?: boolean; + tableName: string; + }): Promise; + createMemory(memory: Memory, tableName: string, unique?: boolean): Promise; + updateMemory(memory: Partial & { id: UUID; metadata?: MemoryMetadata }): Promise; + deleteMemory(memoryId: UUID): Promise; + deleteAllMemories(roomId: UUID, tableName: string): Promise; + countMemories(roomId: UUID, unique?: boolean, tableName?: string): Promise; + createWorld(world: World): Promise; + getWorld(id: UUID): Promise; + getAllWorlds(): Promise; + updateWorld(world: World): Promise; + getRoom(roomId: UUID): Promise; + createRoom({ id, name, source, type, channelId, serverId, worldId }: Room): Promise; + deleteRoom(roomId: UUID): Promise; + updateRoom(room: Room): Promise; + getRoomsForParticipant(entityId: UUID): Promise; + getRoomsForParticipants(userIds: UUID[]): Promise; + getRooms(worldId: UUID): Promise; + addParticipant(entityId: UUID, roomId: UUID): Promise; + removeParticipant(entityId: UUID, roomId: UUID): Promise; + getParticipantsForEntity(entityId: UUID): Promise; + getParticipantsForRoom(roomId: UUID): Promise; + getParticipantUserState(roomId: UUID, entityId: UUID): Promise<'FOLLOWED' | 'MUTED' | null>; + setParticipantUserState( + roomId: UUID, + entityId: UUID, + state: 'FOLLOWED' | 'MUTED' | null + ): Promise; + createRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + tags?: string[]; + metadata?: { [key: string]: any }; + }): Promise; + updateRelationship(relationship: Relationship): Promise; + getRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + }): Promise; + getRelationships(params: { entityId: UUID; tags?: string[] }): Promise; + ensureEmbeddingDimension(dimension: number): Promise; + getCache(key: string): Promise; + setCache(key: string, value: T): Promise; + deleteCache(key: string): Promise; + createTask(task: Task): Promise; + getTasks(params: { roomId?: UUID; tags?: string[] }): Promise; + getTask(id: UUID): Promise; + getTasksByName(name: string): Promise; + updateTask(id: UUID, task: Partial): Promise; + deleteTask(id: UUID): Promise; +} +⋮---- +init(): Promise; +close(): Promise; +getAgent(agentId: UUID): Promise; +getAgents(): Promise; +createAgent(agent: Partial): Promise; +updateAgent(agentId: UUID, agent: Partial): Promise; +deleteAgent(agentId: UUID): Promise; +ensureAgentExists(agent: Partial): Promise; +ensureEmbeddingDimension(dimension: number): Promise; +getEntityById(entityId: UUID): Promise; +getEntitiesForRoom(roomId: UUID, includeComponents?: boolean): Promise; +createEntity(entity: Entity): Promise; +updateEntity(entity: Entity): Promise; +getComponent( + entityId: UUID, + type: string, + worldId?: UUID, + sourceEntityId?: UUID + ): Promise; +getComponents(entityId: UUID, worldId?: UUID, sourceEntityId?: UUID): Promise; +createComponent(component: Component): Promise; +updateComponent(component: Component): Promise; +deleteComponent(componentId: UUID): Promise; +getMemories(params: { + entityId?: UUID; + agentId?: UUID; + roomId?: UUID; + count?: number; + unique?: boolean; + tableName: string; + start?: number; + end?: number; + }): Promise; +getMemoryById(id: UUID): Promise; +getMemoriesByIds(ids: UUID[], tableName?: string): Promise; +getMemoriesByRoomIds(params: { + tableName: string; + roomIds: UUID[]; + limit?: number; + }): Promise; +getCachedEmbeddings(params: { + query_table_name: string; + query_threshold: number; + query_input: string; + query_field_name: string; + query_field_sub_name: string; + query_match_count: number; +}): Promise< +log(params: { + body: { [key: string]: unknown }; + entityId: UUID; + roomId: UUID; + type: string; + }): Promise; +getLogs(params: { + entityId: UUID; + roomId?: UUID; + type?: string; + count?: number; + offset?: number; + }): Promise; +deleteLog(logId: UUID): Promise; +searchMemories(params: { + embedding: number[]; + match_threshold?: number; + count?: number; + roomId?: UUID; + unique?: boolean; + tableName: string; + }): Promise; +createMemory(memory: Memory, tableName: string, unique?: boolean): Promise; +updateMemory(memory: Partial & +deleteMemory(memoryId: UUID): Promise; +deleteAllMemories(roomId: UUID, tableName: string): Promise; +countMemories(roomId: UUID, unique?: boolean, tableName?: string): Promise; +createWorld(world: World): Promise; +getWorld(id: UUID): Promise; +getAllWorlds(): Promise; +updateWorld(world: World): Promise; +getRoom(roomId: UUID): Promise; +createRoom( +deleteRoom(roomId: UUID): Promise; +updateRoom(room: Room): Promise; +getRoomsForParticipant(entityId: UUID): Promise; +getRoomsForParticipants(userIds: UUID[]): Promise; +getRooms(worldId: UUID): Promise; +addParticipant(entityId: UUID, roomId: UUID): Promise; +removeParticipant(entityId: UUID, roomId: UUID): Promise; +getParticipantsForEntity(entityId: UUID): Promise; +getParticipantsForRoom(roomId: UUID): Promise; +getParticipantUserState(roomId: UUID, entityId: UUID): Promise<'FOLLOWED' | 'MUTED' | null>; +setParticipantUserState( + roomId: UUID, + entityId: UUID, + state: 'FOLLOWED' | 'MUTED' | null + ): Promise; +createRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + tags?: string[]; + metadata?: { [key: string]: any }; + }): Promise; +updateRelationship(relationship: Relationship): Promise; +getRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + }): Promise; +getRelationships(params: +⋮---- +getCache(key: string): Promise; +setCache(key: string, value: T): Promise; +deleteCache(key: string): Promise; +createTask(task: Task): Promise; +getTasks(params: +getTask(id: UUID): Promise; +getTasksByName(name: string): Promise; +updateTask(id: UUID, task: Partial): Promise; +deleteTask(id: UUID): Promise; +⋮---- +export interface EmbeddingSearchResult { + embedding: number[]; + levenshtein_score: number; +} +export interface MemoryRetrievalOptions { + roomId: UUID; + count?: number; + unique?: boolean; + start?: number; + end?: number; + agentId?: UUID; +} +export interface MemorySearchOptions { + embedding: number[]; + match_threshold?: number; + count?: number; + roomId: UUID; + agentId?: UUID; + unique?: boolean; + metadata?: Partial; +} +export interface MultiRoomMemoryOptions { + roomIds: UUID[]; + limit?: number; + agentId?: UUID; +} +export interface UnifiedMemoryOptions { + roomId: UUID; + limit?: number; + agentId?: UUID; + unique?: boolean; + start?: number; + end?: number; +} +export interface UnifiedSearchOptions extends UnifiedMemoryOptions { + embedding: number[]; + similarity?: number; +} +export type CacheOptions = { + expires?: number; +}; +export interface IAgentRuntime extends IDatabaseAdapter { + agentId: UUID; + character: Character; + providers: Provider[]; + actions: Action[]; + evaluators: Evaluator[]; + plugins: Plugin[]; + services: Map; + events: Map Promise)[]>; + fetch?: typeof fetch | null; + routes: Route[]; + registerPlugin(plugin: Plugin): Promise; + initialize(): Promise; + getKnowledge(message: Memory): Promise; + addKnowledge( + item: KnowledgeItem, + options: { + targetTokens: number; + overlap: number; + modelContextSize: number; + } + ): Promise; + getService(service: ServiceTypeName | string): T | null; + getAllServices(): Map; + registerService(service: typeof Service): void; + registerDatabaseAdapter(adapter: IDatabaseAdapter): void; + setSetting(key: string, value: string | boolean | null | any, secret: boolean): void; + getSetting(key: string): string | boolean | null | any; + getConversationLength(): number; + processActions( + message: Memory, + responses: Memory[], + state?: State, + callback?: HandlerCallback + ): Promise; + evaluate( + message: Memory, + state?: State, + didRespond?: boolean, + callback?: HandlerCallback, + responses?: Memory[] + ): Promise; + registerProvider(provider: Provider): void; + registerAction(action: Action): void; + registerEvaluator(evaluator: Evaluator): void; + ensureConnection({ + entityId, + roomId, + userName, + name, + source, + channelId, + serverId, + type, + worldId, + }: { + entityId: UUID; + roomId: UUID; + userName?: string; + name?: string; + source?: string; + channelId?: string; + serverId?: string; + type: ChannelType; + worldId?: UUID; + }): Promise; + ensureParticipantInRoom(entityId: UUID, roomId: UUID): Promise; + ensureWorldExists(world: World): Promise; + ensureRoomExists(room: Room): Promise; + composeState(message: Memory, filterList?: string[], includeList?: string[]): Promise; + useModel( + modelType: T, + params: Omit | any + ): Promise; + registerModel(modelType: ModelTypeName | string, handler: (params: any) => Promise): void; + getModel( + modelType: ModelTypeName | string + ): ((runtime: IAgentRuntime, params: any) => Promise) | undefined; + registerEvent(event: string, handler: (params: any) => Promise): void; + getEvent(event: string): ((params: any) => Promise)[] | undefined; + emitEvent(event: string | string[], params: any): Promise; + registerTaskWorker(taskHandler: TaskWorker): void; + getTaskWorker(name: string): TaskWorker | undefined; + stop(): Promise; + addEmbeddingToMemory(memory: Memory): Promise; +} +⋮---- +registerPlugin(plugin: Plugin): Promise; +initialize(): Promise; +getKnowledge(message: Memory): Promise; +addKnowledge( + item: KnowledgeItem, + options: { + targetTokens: number; + overlap: number; + modelContextSize: number; + } + ): Promise; +getService(service: ServiceTypeName | string): T | null; +getAllServices(): Map; +registerService(service: typeof Service): void; +registerDatabaseAdapter(adapter: IDatabaseAdapter): void; +setSetting(key: string, value: string | boolean | null | any, secret: boolean): void; +getSetting(key: string): string | boolean | null | any; +getConversationLength(): number; +processActions( + message: Memory, + responses: Memory[], + state?: State, + callback?: HandlerCallback + ): Promise; +evaluate( + message: Memory, + state?: State, + didRespond?: boolean, + callback?: HandlerCallback, + responses?: Memory[] + ): Promise; +registerProvider(provider: Provider): void; +registerAction(action: Action): void; +registerEvaluator(evaluator: Evaluator): void; +ensureConnection({ + entityId, + roomId, + userName, + name, + source, + channelId, + serverId, + type, + worldId, + }: { + entityId: UUID; + roomId: UUID; + userName?: string; + name?: string; + source?: string; + channelId?: string; + serverId?: string; + type: ChannelType; + worldId?: UUID; + }): Promise; +ensureParticipantInRoom(entityId: UUID, roomId: UUID): Promise; +ensureWorldExists(world: World): Promise; +ensureRoomExists(room: Room): Promise; +composeState(message: Memory, filterList?: string[], includeList?: string[]): Promise; +useModel( + modelType: T, + params: Omit | any + ): Promise; +registerModel(modelType: ModelTypeName | string, handler: (params: any) +getModel( + modelType: ModelTypeName | string +): ((runtime: IAgentRuntime, params: any) +registerEvent(event: string, handler: (params: any) +getEvent(event: string): ((params: any) +emitEvent(event: string | string[], params: any): Promise; +registerTaskWorker(taskHandler: TaskWorker): void; +getTaskWorker(name: string): TaskWorker | undefined; +stop(): Promise; +addEmbeddingToMemory(memory: Memory): Promise; +⋮---- +export type KnowledgeItem = { + id: UUID; + content: Content; + metadata?: MemoryMetadata; +}; +export enum KnowledgeScope { + SHARED = 'shared', + PRIVATE = 'private', +} +export enum CacheKeyPrefix { + KNOWLEDGE = 'knowledge', +} +export interface DirectoryItem { + directory: string; + shared?: boolean; +} +export interface ChunkRow { + id: string; +} +export type GenerateTextParams = { + runtime: IAgentRuntime; + prompt: string; + modelType: ModelTypeName; + maxTokens?: number; + temperature?: number; + frequencyPenalty?: number; + presencePenalty?: number; + stopSequences?: string[]; +}; +export interface TokenizeTextParams { + prompt: string; + modelType: ModelTypeName; +} +export interface DetokenizeTextParams { + tokens: number[]; + modelType: ModelTypeName; +} +export interface IVideoService extends Service { + isVideoUrl(url: string): boolean; + fetchVideoInfo(url: string): Promise; + downloadVideo(videoInfo: Media): Promise; + processVideo(url: string, runtime: IAgentRuntime): Promise; +} +⋮---- +isVideoUrl(url: string): boolean; +fetchVideoInfo(url: string): Promise; +downloadVideo(videoInfo: Media): Promise; +processVideo(url: string, runtime: IAgentRuntime): Promise; +⋮---- +export interface IBrowserService extends Service { + getPageContent( + url: string, + runtime: IAgentRuntime + ): Promise<{ title: string; description: string; bodyContent: string }>; +} +⋮---- +getPageContent( + url: string, + runtime: IAgentRuntime +): Promise< +⋮---- +export interface IPdfService extends Service { + convertPdfToText(pdfBuffer: Buffer): Promise; +} +⋮---- +convertPdfToText(pdfBuffer: Buffer): Promise; +⋮---- +export interface IFileService extends Service { + uploadFile( + imagePath: string, + subDirectory: string, + useSignedUrl: boolean, + expiresIn: number + ): Promise<{ + success: boolean; + url?: string; + error?: string; + }>; + generateSignedUrl(fileName: string, expiresIn: number): Promise; +} +⋮---- +uploadFile( + imagePath: string, + subDirectory: string, + useSignedUrl: boolean, + expiresIn: number +): Promise< +generateSignedUrl(fileName: string, expiresIn: number): Promise; +⋮---- +export interface TestCase { + name: string; + fn: (runtime: IAgentRuntime) => Promise | void; +} +export interface TestSuite { + name: string; + tests: TestCase[]; +} +export interface TeeAgent { + id: string; + agentId: string; + agentName: string; + createdAt: number; + publicKey: string; + attestation: string; +} +export enum TEEMode { + OFF = 'OFF', + LOCAL = 'LOCAL', + DOCKER = 'DOCKER', + PRODUCTION = 'PRODUCTION', +} +export interface RemoteAttestationQuote { + quote: string; + timestamp: number; +} +export interface DeriveKeyAttestationData { + agentId: string; + publicKey: string; + subject?: string; +} +export interface RemoteAttestationMessage { + agentId: string; + timestamp: number; + message: { + entityId: string; + roomId: string; + content: string; + }; +} +export enum TeeType { + TDX_DSTACK = 'tdx_dstack', +} +export interface TeeVendorConfig { + [key: string]: unknown; +} +export interface TeePluginConfig { + vendor?: string; + vendorConfig?: TeeVendorConfig; +} +export interface TaskWorker { + name: string; + execute: ( + runtime: IAgentRuntime, + options: { [key: string]: unknown }, + task: Task + ) => Promise; + validate?: (runtime: IAgentRuntime, message: Memory, state: State) => Promise; +} +export interface Task { + id?: UUID; + name: string; + updatedAt?: number; + metadata?: { + updateInterval?: number; + options?: { + name: string; + description: string; + }[]; + [key: string]: unknown; + }; + description: string; + roomId?: UUID; + worldId?: UUID; + tags: string[]; +} +export enum Role { + OWNER = 'OWNER', + ADMIN = 'ADMIN', + NONE = 'NONE', +} +export interface Setting { + name: string; + description: string; + usageDescription: string; + value: string | boolean | null; + required: boolean; + public?: boolean; + secret?: boolean; + validation?: (value: any) => boolean; + dependsOn?: string[]; + onSetAction?: (value: any) => string; + visibleIf?: (settings: { [key: string]: Setting }) => boolean; +} +export interface WorldSettings { + [key: string]: Setting; +} +export interface OnboardingConfig { + settings: { + [key: string]: Omit; + }; +} +export interface BaseModelParams { + runtime: IAgentRuntime; +} +export interface TextGenerationParams extends BaseModelParams { + prompt: string; + temperature?: number; + maxTokens?: number; + stopSequences?: string[]; + frequencyPenalty?: number; + presencePenalty?: number; +} +export interface TextEmbeddingParams extends BaseModelParams { + text: string; +} +export interface TokenizeTextParams extends BaseModelParams { + prompt: string; + modelType: ModelTypeName; +} +export interface DetokenizeTextParams extends BaseModelParams { + tokens: number[]; + modelType: ModelTypeName; +} +export interface ImageGenerationParams extends BaseModelParams { + prompt: string; + size?: string; + count?: number; +} +export interface ImageDescriptionParams extends BaseModelParams { + imageUrl: string; + prompt?: string; +} +export interface TranscriptionParams extends BaseModelParams { + audioUrl: string; + prompt?: string; +} +export interface TextToSpeechParams extends BaseModelParams { + text: string; + voice?: string; + speed?: number; +} +export interface AudioProcessingParams extends BaseModelParams { + audioUrl: string; + processingType: string; +} +export interface VideoProcessingParams extends BaseModelParams { + videoUrl: string; + processingType: string; +} +export type JSONSchema = { + type: string; + properties?: Record; + required?: string[]; + items?: JSONSchema; + [key: string]: any; +}; +export interface ObjectGenerationParams extends BaseModelParams { + prompt: string; + schema?: JSONSchema; + output?: 'object' | 'array' | 'enum'; + enumValues?: string[]; + modelType?: ModelTypeName; + temperature?: number; + stopSequences?: string[]; +} +export interface ModelParamsMap { + [ModelType.TEXT_SMALL]: TextGenerationParams; + [ModelType.TEXT_LARGE]: TextGenerationParams; + [ModelType.TEXT_EMBEDDING]: TextEmbeddingParams | string | null; + [ModelType.TEXT_TOKENIZER_ENCODE]: TokenizeTextParams; + [ModelType.TEXT_TOKENIZER_DECODE]: DetokenizeTextParams; + [ModelType.TEXT_REASONING_SMALL]: TextGenerationParams; + [ModelType.TEXT_REASONING_LARGE]: TextGenerationParams; + [ModelType.IMAGE]: ImageGenerationParams; + [ModelType.IMAGE_DESCRIPTION]: ImageDescriptionParams | string; + [ModelType.TRANSCRIPTION]: TranscriptionParams | Buffer | string; + [ModelType.TEXT_TO_SPEECH]: TextToSpeechParams | string; + [ModelType.AUDIO]: AudioProcessingParams; + [ModelType.VIDEO]: VideoProcessingParams; + [ModelType.OBJECT_SMALL]: ObjectGenerationParams; + [ModelType.OBJECT_LARGE]: ObjectGenerationParams; + [key: string]: BaseModelParams | any; +} +export interface ModelResultMap { + [ModelType.TEXT_SMALL]: string; + [ModelType.TEXT_LARGE]: string; + [ModelType.TEXT_EMBEDDING]: number[]; + [ModelType.TEXT_TOKENIZER_ENCODE]: number[]; + [ModelType.TEXT_TOKENIZER_DECODE]: string; + [ModelType.TEXT_REASONING_SMALL]: string; + [ModelType.TEXT_REASONING_LARGE]: string; + [ModelType.IMAGE]: { url: string }[]; + [ModelType.IMAGE_DESCRIPTION]: { title: string; description: string }; + [ModelType.TRANSCRIPTION]: string; + [ModelType.TEXT_TO_SPEECH]: Readable | Buffer; + [ModelType.AUDIO]: any; + [ModelType.VIDEO]: any; + [ModelType.OBJECT_SMALL]: any; + [ModelType.OBJECT_LARGE]: any; + [key: string]: any; +} +export enum EventType { + WORLD_JOINED = 'WORLD_JOINED', + WORLD_CONNECTED = 'WORLD_CONNECTED', + WORLD_LEFT = 'WORLD_LEFT', + ENTITY_JOINED = 'ENTITY_JOINED', + ENTITY_LEFT = 'ENTITY_LEFT', + ENTITY_UPDATED = 'ENTITY_UPDATED', + ROOM_JOINED = 'ROOM_JOINED', + ROOM_LEFT = 'ROOM_LEFT', + MESSAGE_RECEIVED = 'MESSAGE_RECEIVED', + MESSAGE_SENT = 'MESSAGE_SENT', + VOICE_MESSAGE_RECEIVED = 'VOICE_MESSAGE_RECEIVED', + VOICE_MESSAGE_SENT = 'VOICE_MESSAGE_SENT', + REACTION_RECEIVED = 'REACTION_RECEIVED', + POST_GENERATED = 'POST_GENERATED', + INTERACTION_RECEIVED = 'INTERACTION_RECEIVED', + RUN_STARTED = 'RUN_STARTED', + RUN_ENDED = 'RUN_ENDED', + RUN_TIMEOUT = 'RUN_TIMEOUT', + ACTION_STARTED = 'ACTION_STARTED', + ACTION_COMPLETED = 'ACTION_COMPLETED', + EVALUATOR_STARTED = 'EVALUATOR_STARTED', + EVALUATOR_COMPLETED = 'EVALUATOR_COMPLETED', +} +export enum PlatformPrefix { + DISCORD = 'DISCORD', + TELEGRAM = 'TELEGRAM', + TWITTER = 'TWITTER', +} +export interface EventPayload { + runtime: IAgentRuntime; + source: string; +} +export interface WorldPayload extends EventPayload { + world: World; + rooms: Room[]; + entities: Entity[]; +} +export interface EntityPayload extends EventPayload { + entityId: UUID; + worldId?: UUID; + roomId?: UUID; + metadata?: { + orginalId: string; + username: string; + displayName?: string; + [key: string]: any; + }; +} +export interface MessagePayload extends EventPayload { + message: Memory; + callback?: HandlerCallback; +} +export interface InvokePayload extends EventPayload { + worldId: UUID; + userId: string; + roomId: UUID; + callback?: HandlerCallback; +} +export interface RunEventPayload extends EventPayload { + runId: UUID; + messageId: UUID; + roomId: UUID; + entityId: UUID; + startTime: number; + status: 'started' | 'completed' | 'timeout'; + endTime?: number; + duration?: number; + error?: string; +} +export interface ActionEventPayload extends EventPayload { + actionId: UUID; + actionName: string; + startTime?: number; + completed?: boolean; + error?: Error; +} +export interface EvaluatorEventPayload extends EventPayload { + evaluatorId: UUID; + evaluatorName: string; + startTime?: number; + completed?: boolean; + error?: Error; +} +export type MessageReceivedHandlerParams = { + runtime: IAgentRuntime; + message: Memory; + callback: HandlerCallback; +}; +export interface EventPayloadMap { + [EventType.WORLD_JOINED]: WorldPayload; + [EventType.WORLD_CONNECTED]: WorldPayload; + [EventType.WORLD_LEFT]: WorldPayload; + [EventType.ENTITY_JOINED]: EntityPayload; + [EventType.ENTITY_LEFT]: EntityPayload; + [EventType.ENTITY_UPDATED]: EntityPayload; + [EventType.MESSAGE_RECEIVED]: MessagePayload; + [EventType.MESSAGE_SENT]: MessagePayload; + [EventType.REACTION_RECEIVED]: MessagePayload; + [EventType.POST_GENERATED]: InvokePayload; + [EventType.INTERACTION_RECEIVED]: MessagePayload; + [EventType.RUN_STARTED]: RunEventPayload; + [EventType.RUN_ENDED]: RunEventPayload; + [EventType.RUN_TIMEOUT]: RunEventPayload; + [EventType.ACTION_STARTED]: ActionEventPayload; + [EventType.ACTION_COMPLETED]: ActionEventPayload; + [EventType.EVALUATOR_STARTED]: EvaluatorEventPayload; + [EventType.EVALUATOR_COMPLETED]: EvaluatorEventPayload; +} +export type EventHandler = ( + payload: EventPayloadMap[T] +) => Promise; +export enum SOCKET_MESSAGE_TYPE { + ROOM_JOINING = 1, + SEND_MESSAGE = 2, + MESSAGE = 3, + ACK = 4, + THINKING = 5, +} +export interface MessageMemory extends Memory { + metadata: MessageMetadata; + content: Content & { + text: string; + }; +} +export function createMessageMemory(params: { + id?: UUID; + entityId: UUID; + agentId?: UUID; + roomId: UUID; + content: Content & { text: string }; + embedding?: number[]; +}): MessageMemory +export interface TypedService extends Service { + config: ConfigType; + process(input: unknown): Promise; +} +⋮---- +process(input: unknown): Promise; +⋮---- +export function getTypedService>( + runtime: IAgentRuntime, + serviceType: ServiceTypeName +): T | null +export function isDocumentMetadata(metadata: MemoryMetadata): metadata is DocumentMetadata +export function isFragmentMetadata(metadata: MemoryMetadata): metadata is FragmentMetadata +export function isMessageMetadata(metadata: MemoryMetadata): metadata is MessageMetadata +export function isDescriptionMetadata(metadata: MemoryMetadata): metadata is DescriptionMetadata +export function isCustomMetadata(metadata: MemoryMetadata): metadata is CustomMetadata +export interface ServiceError { + code: string; + message: string; + details?: unknown; + cause?: Error; +} +export function getVideoService(runtime: IAgentRuntime): IVideoService | null +export function getBrowserService(runtime: IAgentRuntime): IBrowserService | null +export function getPdfService(runtime: IAgentRuntime): IPdfService | null +export function getFileService(runtime: IAgentRuntime): IFileService | null +export function isDocumentMemory( + memory: Memory +): memory is Memory & +export function isFragmentMemory( + memory: Memory +): memory is Memory & +export function getMemoryText(memory: Memory, defaultValue = ''): string +/** + * Safely create a ServiceError from any caught error + */ +export function createServiceError(error: unknown, code = 'UNKNOWN_ERROR'): ServiceError +export type StateValue = string | number | boolean | null | StateObject | StateArray; +export interface StateObject { + [key: string]: StateValue; +} +export type StateArray = StateValue[]; +export interface EnhancedState { + values: StateObject; + data: StateObject; + text: string; + [key: string]: StateValue; +} +export type ComponentData = Record; +export type EventDataObject = Record; +export type TypedEventHandler = (data: EventDataObject) => Promise | void; +export type DbConnection = unknown; +export type MetadataObject = Record; +export type ModelHandler = ( + runtime: IAgentRuntime, + params: Record +) => Promise; +export type ServiceConfig = Record; +```` + +## File: packages/core/src/uuid.ts +````typescript +import { sha1 } from 'js-sha1'; +import { z } from 'zod'; +import type { UUID } from './types'; +⋮---- +export function validateUuid(value: unknown): UUID | null +export function stringToUuid(target: string | number): UUID +⋮---- +const _uint8ToHex = (ubyte: number): string => +const _uint8ArrayToHex = (buf: Uint8Array): string => +```` + +## File: packages/docs/docs/core/actions.md +````markdown +--- +sidebar_position: 6 +--- + +# ⚡ Actions + +Actions define how agents respond to and interact with messages. They enable agents to perform tasks beyond simple message responses by integrating with external systems and modifying behavior. + +## Overview + +Actions are core components that define an agent's capabilities and how it can respond to conversations. Each action represents a distinct operation that an agent can perform, ranging from simple replies to complex interactions with external systems. + +1. Structure: + +An Action consists of: + +- `name`: Unique identifier +- `similes`: Alternative names/triggers +- `description`: Purpose and usage explanation +- `validate`: Function to check if action is appropriate +- `handler`: Core implementation logic +- `examples`: Sample usage patterns +- `suppressInitialMessage`: Optional flag to suppress initial response + +2. Agent Decision Flow: + +When a message is received: + +- The agent evaluates all available actions using their validation functions +- Valid actions are provided to the LLM via the `actionsProvider` +- The LLM decides which action(s) to execute +- Each action's handler generates a response including a "thought" component (agent's internal reasoning) +- The response is processed and sent back to the conversation + +3. Integration: + +Actions work in concert with: + +- **Providers** - Supply context before the agent decides what action to take +- **Evaluators** - Process conversations after actions to extract insights and update memory +- **Services** - Enable actions to interact with external systems + +--- + +## Implementation + +The core Action interface includes the following components: + +```typescript +interface Action { + name: string; // Unique identifier + similes: string[]; // Alternative names/triggers + description: string; // Purpose and usage explanation + validate: (runtime: IAgentRuntime, message: Memory, state?: State) => Promise; + handler: ( + runtime: IAgentRuntime, + message: Memory, + state?: State, + options?: any, + callback?: HandlerCallback + ) => Promise; + examples: ActionExample[][]; + suppressInitialMessage?: boolean; // Optional flag +} + +// Handler callback for generating responses +type HandlerCallback = (content: Content) => Promise; + +// Response content structure +interface Content { + text: string; + thought?: string; // Internal reasoning (not shown to users) + actions?: string[]; // List of action names being performed + action?: string; // Legacy single action name + attachments?: Attachment[]; // Optional media attachments +} +``` + +### Basic Action Template + +Here's a simplified template for creating a custom action: + +```typescript +const customAction: Action = { + name: 'CUSTOM_ACTION', + similes: ['ALTERNATE_NAME', 'OTHER_TRIGGER'], + description: 'Detailed description of when and how to use this action', + + validate: async (runtime: IAgentRuntime, message: Memory, state?: State) => { + // Logic to determine if this action applies to the current message + // Should be efficient and quick to check + return true; // Return true if action is valid for this message + }, + + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state?: State, + options?: any, + callback?: HandlerCallback + ) => { + // Implementation logic - what the action actually does + + // Generate a response with thought and text components + const responseContent = { + thought: 'Internal reasoning about what to do (not shown to users)', + text: 'The actual message to send to the conversation', + actions: ['CUSTOM_ACTION'], // List of actions being performed + }; + + // Send the response using the callback + if (callback) { + await callback(responseContent); + } + + return true; // Return true if action executed successfully + }, + + examples: [ + [ + { + name: '{{name1}}', + content: { text: 'Trigger message' }, + }, + { + name: '{{name2}}', + content: { + text: 'Response', + thought: 'Internal reasoning', + actions: ['CUSTOM_ACTION'], + }, + }, + ], + ], +}; +``` + +### Character File Example + +Actions can be referenced in character files to define how an agent should respond to specific types of messages: + +```json +"messageExamples": [ + [ + { + "user": "{{user1}}", + "content": { + "text": "Can you help transfer some SOL?" + } + }, + { + "user": "SBF", + "content": { + "text": "yeah yeah for sure, sending SOL is pretty straightforward. just need the recipient and amount. everything else is basically fine, trust me.", + "actions": ["SEND_SOL"] + } + } + ] +] +``` + +### The Reply Action + +The most fundamental action is the `REPLY` action, which allows agents to respond to messages with text. It serves as the default action when no specialized behavior is needed: + +```typescript +const replyAction: Action = { + name: 'REPLY', + similes: ['GREET', 'REPLY_TO_MESSAGE', 'SEND_REPLY', 'RESPOND', 'RESPONSE'], + description: 'Replies to the current conversation with the text from the generated message.', + + validate: async (_runtime: IAgentRuntime) => true, // Always valid + + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state: State, + _options: any, + callback: HandlerCallback + ) => { + // Compose state with necessary providers + state = await runtime.composeState(message, [ + ...(message.content.providers ?? []), + 'RECENT_MESSAGES', + ]); + + // Generate response using LLM + const response = await runtime.useModel(ModelType.TEXT_SMALL, { + prompt: composePromptFromState({ + state, + template: replyTemplate, + }), + }); + + // Parse and format response + const responseContentObj = parseJSONObjectFromText(response); + const responseContent = { + thought: responseContentObj.thought, + text: responseContentObj.message || '', + actions: ['REPLY'], + }; + + // Send response via callback + await callback(responseContent); + return true; + }, + + examples: [ + /* Examples omitted for brevity */ + ], +}; +``` + +--- + +## Actions Provider Integration + +The actions provider is responsible for making valid actions available to the agent's reasoning process. When a message is received: + +1. The provider validates all available actions against the current message +2. It formats the valid actions for inclusion in the agent context +3. This formatted information is used by the agent to decide which action(s) to take + +```typescript +const actionsProvider: Provider = { + name: 'ACTIONS', + description: 'Possible response actions', + position: -1, // High priority provider + get: async (runtime: IAgentRuntime, message: Memory, state: State) => { + // Validate all actions for this message + const actionPromises = runtime.actions.map(async (action: Action) => { + const result = await action.validate(runtime, message, state); + return result ? action : null; + }); + + const resolvedActions = await Promise.all(actionPromises); + const actionsData = resolvedActions.filter(Boolean); + + // Format action information for the agent + const values = { + actionNames: `Possible response actions: ${formatActionNames(actionsData)}`, + actions: formatActions(actionsData), + actionExamples: composeActionExamples(actionsData, 10), + }; + + // Return data, values, and text representation + return { + data: { actionsData }, + values, + text: [values.actionNames, values.actionExamples, values.actions] + .filter(Boolean) + .join('\n\n'), + }; + }, +}; +``` + +## Example Implementations + +ElizaOS includes a wide variety of predefined actions across various plugins in the ecosystem. Here are some key categories: + +### Communication Actions + +- **REPLY**: Standard text response +- **CONTINUE**: Extend the conversation +- **IGNORE**: End the conversation or ignore irrelevant messages + +### Blockchain and Token Actions + +- **SEND_TOKEN**: Transfer cryptocurrency +- **CREATE_TOKEN**: Create a new token on a blockchain +- **READ_CONTRACT/WRITE_CONTRACT**: Interact with smart contracts + +### Media and Content Generation + +- **GENERATE_IMAGE**: Create images from text descriptions +- **SEND_GIF**: Share animated content +- **GENERATE_3D**: Create 3D content + +### AI and Agent Management + +- **LAUNCH_AGENT**: Create and start a new agent +- **START_SESSION**: Begin an interactive session +- **GENERATE_MEME**: Create humorous content + +### Example Image Generation Action + +Here's a more detailed example of an image generation action: + +```typescript +const generateImageAction: Action = { + name: 'GENERATE_IMAGE', + similes: ['CREATE_IMAGE', 'MAKE_IMAGE', 'DRAW'], + description: "Generates an image based on the user's description", + suppressInitialMessage: true, // Don't send initial text response + + validate: async (runtime: IAgentRuntime, message: Memory) => { + const text = message.content.text.toLowerCase(); + return ( + text.includes('generate') || + text.includes('create') || + text.includes('draw') || + text.includes('make an image') + ); + }, + + handler: async ( + runtime: IAgentRuntime, + message: Memory, + state?: State, + _options?: any, + callback?: HandlerCallback + ) => { + try { + // Get appropriate service + const imageService = runtime.getService(ServiceType.IMAGE_GENERATION); + + // Generate the response with thought component + const responseContent = { + thought: + "This request is asking for image generation. I'll use the image service to create a visual based on the user's description.", + text: "I'm generating that image for you now...", + actions: ['GENERATE_IMAGE'], + }; + + // Send initial response if callback provided + if (callback) { + await callback(responseContent); + } + + // Generate image + const imageUrl = await imageService.generateImage(message.content.text); + + // Create follow-up message with the generated image + await runtime.createMemory( + { + id: generateId(), + content: { + text: "Here's the image I generated:", + attachments: [ + { + type: 'image', + url: imageUrl, + }, + ], + }, + agentId: runtime.agentId, + roomId: message.roomId, + }, + 'messages' + ); + + return true; + } catch (error) { + console.error('Image generation failed:', error); + + // Send error response if callback provided + if (callback) { + await callback({ + thought: 'The image generation failed due to an error.', + text: "I'm sorry, I wasn't able to generate that image. There was a technical problem.", + actions: ['REPLY'], + }); + } + + return false; + } + }, + + examples: [ + /* Examples omitted for brevity */ + ], +}; +``` + +## Action-Evaluator-Provider Cycle + +Actions are part of a larger cycle in ElizaOS agents: + +1. **Providers** fetch relevant context for decision-making +2. **Actions** execute the agent's chosen response +3. **Evaluators** process the conversation to extract insights +4. These insights are stored in memory +5. Future **Providers** can access these insights +6. This informs future **Actions** + +For example: + +- The FACTS provider retrieves relevant facts about users +- The agent uses this context to decide on an appropriate action +- After the action, the reflection evaluator extracts new facts and relationships +- These are stored in memory and available for future interactions +- This creates a virtuous cycle of continuous learning and improvement + +--- + +## FAQ + +### What are Actions in ElizaOS? + +Actions are core components that define how agents respond to messages and perform tasks. They encapsulate specific behaviors and capabilities, ranging from simple text replies to complex interactions with external systems. + +### How do Actions work? + +When a message is received, the agent evaluates all available actions using their validation functions. The agent then decides which action(s) to execute based on the message content and context. Each action's handler generates a response, which may include text, thought processes, and attachments. + +### What's the difference between actions and evaluators? + +Actions are executed during an agent's response to perform tasks and generate content. Evaluators run after responses to analyze conversations, extract information, and update the agent's memory. Actions are about doing, evaluators are about learning. + +### What role do "thoughts" play in actions? + +The thought component provides an internal reasoning process for the agent, explaining its decision-making. These thoughts aren't shown to users but help with debugging and understanding the agent's behavior. They're similar to the self-reflection component in evaluators. + +### How do I create a custom action? + +Define an action object with a name, similes, description, validation function, handler function, and examples. The validation function determines when the action should be used, while the handler contains the implementation logic and generates a response. + +### Can actions be chained together? + +Yes! Actions can call other actions or services as part of their implementation. This allows for complex workflows that combine multiple capabilities. For example, an action might first reply to a user, then generate an image, and finally store data in a database. + +### How does an agent choose which action to use? + +The agent uses the following process: + +1. All actions are validated against the current message +2. Valid actions are formatted and included in the agent's context +3. The LLM decides which action(s) to execute based on the message and context +4. The chosen action's handler is executed to generate a response + +### How do actions integrate with services? + +Actions often use services to interact with external systems. The action handler can retrieve a service from the runtime (e.g., `imageService = runtime.getService(ServiceType.IMAGE_GENERATION)`) and then call methods on that service to perform operations. + +### What's the difference between `actions` and `action` in responses? + +The `actions` array is the modern way to specify multiple actions being performed in a single response. The singular `action` field is maintained for backward compatibility but is deprecated in favor of the array format. + +### Can I add custom actions to an existing agent? + +Yes! You can create a plugin that defines new actions and then add that plugin to your agent's configuration. This allows you to extend the agent's capabilities without modifying its core implementation. + +## Further Reading + +- [Evaluators](./evaluators.md) +- [Providers](./providers.md) +- [Services](./services.md) +```` + +## File: packages/docs/docs/core/database.md +````markdown +--- +sidebar_position: 7 +--- + +# 💾 Database System + +The ElizaOS database system provides persistent storage capabilities for agents. It handles memory storage, entity relationships, knowledge management, and more through a flexible adapter-based architecture. + +## Overview + +ElizaOS uses a unified database architecture based on Drizzle ORM with adapters that implement the [`IDatabaseAdapter`](/api/interfaces/IDatabaseAdapter) interface. The current release includes support for: + +| Adapter | Best For | Key Features | +| -------------- | --------------------------- | ----------------------------------------------------------------- | +| **PGLite** | Local development & testing | Lightweight PostgreSQL implementation running in Node process | +| **PostgreSQL** | Production deployments | Full PostgreSQL with vector search, scaling, and high reliability | + +Additional database adapters will be supported in future releases as ElizaOS continues to evolve. + +## Core Functionality + +All database adapters extend the `BaseDrizzleAdapter` abstract class, which provides a comprehensive set of methods for managing all aspects of agent data: + +### Entity System + +| Method | Description | +| ---------------------- | ------------------------------------- | +| `createEntity()` | Create a new entity | +| `getEntityById()` | Retrieve an entity by ID | +| `getEntitiesForRoom()` | Get all entities in a room | +| `updateEntity()` | Update entity attributes | +| `getComponent()` | Get a specific component of an entity | +| `getComponents()` | Get all components for an entity | +| `createComponent()` | Add a component to an entity | +| `updateComponent()` | Update a component | +| `deleteComponent()` | Remove a component | + +### Memory Management + +| Method | Description | +| ----------------------------- | ------------------------------------ | +| `createMemory()` | Store a new memory with metadata | +| `getMemoryById()` | Retrieve a specific memory | +| `getMemories()` | Get memories matching criteria | +| `getMemoriesByIds()` | Get multiple memories by IDs | +| `getMemoriesByRoomIds()` | Get memories from multiple rooms | +| `searchMemories()` | Search memories by vector similarity | +| `searchMemoriesByEmbedding()` | Search using raw embedding vector | +| `deleteMemory()` | Remove a specific memory | +| `deleteAllMemories()` | Remove all memories in a room | +| `countMemories()` | Count memories matching criteria | + +### Room & Participant Management + +| Method | Description | +| ---------------------------- | ------------------------------- | +| `createRoom()` | Create a new conversation room | +| `getRoom()` | Get room by ID | +| `getRooms()` | Get all rooms in a world | +| `updateRoom()` | Update room attributes | +| `deleteRoom()` | Remove a room | +| `addParticipant()` | Add entity to room | +| `removeParticipant()` | Remove entity from room | +| `getParticipantsForEntity()` | Get all rooms an entity is in | +| `getParticipantsForRoom()` | List entities in a room | +| `getParticipantUserState()` | Get entity's state in a room | +| `setParticipantUserState()` | Update entity's state in a room | + +### Relationship Management + +| Method | Description | +| ---------------------- | -------------------------------------- | +| `createRelationship()` | Create a relationship between entities | +| `updateRelationship()` | Update relationship attributes | +| `getRelationship()` | Get a specific relationship | +| `getRelationships()` | Get all relationships for an entity | + +### Caching System + +| Method | Description | +| --------------- | ---------------------- | +| `getCache()` | Retrieve cached data | +| `setCache()` | Store data in cache | +| `deleteCache()` | Remove data from cache | + +### World & Task Management + +| Method | Description | +| ------------------ | --------------------------- | +| `createWorld()` | Create a new world | +| `getWorld()` | Get world by ID | +| `getAllWorlds()` | List all worlds | +| `updateWorld()` | Update world attributes | +| `removeWorld()` | Delete a world | +| `createTask()` | Create a new task | +| `getTasks()` | Get tasks matching criteria | +| `getTasksByName()` | Find tasks by name | +| `getTask()` | Get task by ID | +| `updateTask()` | Update task attributes | +| `deleteTask()` | Remove a task | + +### Agent Management + +| Method | Description | +| --------------- | ------------------------- | +| `createAgent()` | Create a new agent record | +| `getAgent()` | Get agent by ID | +| `getAgents()` | List all agents | +| `updateAgent()` | Update agent attributes | +| `deleteAgent()` | Remove an agent | +| `countAgents()` | Count total agents | + +### Embedding & Search + +| Method | Description | +| ----------------------------- | ------------------------------ | +| `ensureEmbeddingDimension()` | Configure embedding dimensions | +| `getCachedEmbeddings()` | Retrieve cached embeddings | +| `searchMemories()` | Vector search for memories | +| `searchMemoriesByEmbedding()` | Advanced vector search | + +## Architecture + +ElizaOS uses a singleton pattern for database connections to ensure efficient resource usage: + +``` +┌─────────────────────────────────────┐ +│ AgentRuntime │ +└───────────────┬─────────────────────┘ + │ + ▼ +┌─────────────────────────────────────┐ +│ IDatabaseAdapter │ +└───────────────┬─────────────────────┘ + │ + ▼ +┌─────────────────────────────────────┐ +│ BaseDrizzleAdapter │ +└───────────────┬─────────────────────┘ + │ + ┌───────┴───────┐ + ▼ ▼ +┌───────────────┐ ┌─────────────────┐ +│ PGLiteAdapter │ │ PostgresAdapter │ +└───────┬───────┘ └────────┬────────┘ + │ │ + ▼ ▼ +┌───────────────┐ ┌─────────────────┐ +│PGLiteManager │ │PostgresManager │ +│ (Singleton) │ │ (Singleton) │ +└───────────────┘ └─────────────────┘ +``` + +Each adapter is associated with a singleton connection manager that ensures only one database connection is maintained per process, regardless of how many agents are running. + +## Implementation + +### Initialization + +The database adapter is initialized through the SQL plugin: + +```typescript +// Plugin registration in project configuration +const project = { + plugins: ['@elizaos/plugin-sql'], + // ... +}; +``` + +The SQL plugin automatically selects and initializes the appropriate database adapter based on environment settings: + +```typescript +function createDatabaseAdapter( + config: { + dataDir?: string; + postgresUrl?: string; + }, + agentId: UUID +): IDatabaseAdapter { + if (config.postgresUrl) { + return new PgDatabaseAdapter(agentId, postgresConnectionManager); + } + + // Default to PGLite + return new PgliteDatabaseAdapter(agentId, pgLiteClientManager); +} +``` + +### Configuration + +Configure the database adapter using environment variables or settings: + +```typescript +// For PostgreSQL +process.env.POSTGRES_URL = 'postgresql://username:password@localhost:5432/elizaos'; + +// For PGLite (default) +process.env.PGLITE_DATA_DIR = './elizadb'; // Optional, defaults to './pglite' +``` + +### Retry Logic & Error Handling + +The database system includes built-in retry logic with exponential backoff and jitter: + +```typescript +protected async withRetry(operation: () => Promise): Promise { + let attempt = 0; + let lastError: Error | null = null; + + while (attempt < this.maxRetries) { + try { + return await operation(); + } catch (error) { + lastError = error as Error; + const isRetryable = this.isRetryableError(error); + + if (!isRetryable) { + break; + } + + // Calculate delay with exponential backoff and jitter + const delay = Math.min( + this.baseDelay * Math.pow(2, attempt) + Math.random() * this.jitterMax, + this.maxDelay + ); + + await new Promise(resolve => setTimeout(resolve, delay)); + attempt++; + } + } + + throw lastError; +} +``` + +## Example Usage + +Here are examples of common database operations: + +### Store a Memory + +```typescript +await runtime.createMemory( + { + entityId: message.entityId, + agentId: runtime.agentId, + content: { text: 'Important information to remember' }, + roomId: message.roomId, + embedding: await runtime.useModel(ModelType.TEXT_EMBEDDING, { + text: 'Important information to remember', + }), + }, + 'facts' +); +``` + +### Search for Memories + +```typescript +const embedding = await runtime.useModel(ModelType.TEXT_EMBEDDING, { + text: 'What did we discuss about databases?', +}); + +const relevantMemories = await runtime.searchMemories({ + tableName: 'messages', + embedding, + roomId: message.roomId, + count: 5, +}); +``` + +### Manage Entity Relationships + +```typescript +// Create a relationship between entities +await runtime.createRelationship({ + sourceEntityId: userEntityId, + targetEntityId: agentEntityId, + tags: ['friend', 'frequent_interaction'], + metadata: { + interactions: 42, + trust_level: 'high', + }, +}); + +// Retrieve relationships +const relationships = await runtime.getRelationships({ + entityId: userEntityId, + tags: ['friend'], +}); +``` + +## Database Schema + +The schema is managed by Drizzle ORM and includes the following key tables: + +### Core Tables + +- **entities**: The fundamental objects in the system (users, agents, etc.) +- **components**: Modular data attached to entities (profiles, settings, etc.) +- **memories**: Conversation history and other remembered information +- **relationships**: Connections between entities +- **rooms**: Conversation channels +- **participants**: Entity participation in rooms +- **worlds**: Container for multiple rooms +- **tasks**: Scheduled or queued operations +- **cache**: Temporary key-value storage +- **agents**: Agent configuration and state + +### Entity-Component System + +ElizaOS uses an entity-component architecture where: + +- Entities are the base objects (users, agents, etc.) +- Components are pieces of data attached to entities +- This allows for flexible data modeling and extension + +For example, a user entity might have profile, preferences, and authentication components. + +## Vector Search + +Both adapters support vector-based semantic search with some differences: + +- **PostgreSQL**: Uses pgvector extension for optimized vector operations +- **PGLite**: Implements vector search in JavaScript with an efficient algorithm + +The embedding dimension is configurable based on the model used: + +```typescript +await adapter.ensureEmbeddingDimension(1536); // For OpenAI embeddings +``` + +## FAQ + +### How do I choose between PGLite and PostgreSQL? + +- Use **PGLite** for: + + - Local development and testing + - Single-user deployments + - Situations where installing PostgreSQL is impractical + +- Use **PostgreSQL** for: + - Production deployments + - Multi-user systems + - High-volume data + - When you need advanced scaling features + +### How do I configure the database connection? + +For PostgreSQL, set the `POSTGRES_URL` environment variable: + +``` +POSTGRES_URL=postgresql://username:password@localhost:5432/elizaos +``` + +For PGLite, set the data directory (optional): + +``` +PGLITE_DATA_DIR=./my-data +``` + +### How can I inspect the database contents? + +For PostgreSQL, use standard PostgreSQL tools like pgAdmin or psql. + +For PGLite, the data is stored in the specified data directory as files. You can use tools like DB Browser for SQLite to inspect the SQLite files that PGLite generates. + +### How do I migrate between different database adapters? + +Currently, there's no built-in migration tool between adapters. For production systems, it's recommended to start with PostgreSQL if you anticipate needing its features. + +### What about vector embedding dimension mismatches? + +The system automatically handles embedding dimensions based on the model used. If you change embedding models, make sure to: + +1. Set the correct dimension with `ensureEmbeddingDimension()` +2. Be aware that mixing different dimensions in the same database can cause issues + +### How does the entity-component system work? + +The entity-component system (ECS) provides a flexible way to model data: + +- **Entities** are base objects with unique IDs +- **Components** are pieces of data attached to entities +- This allows for dynamic composition of objects without complex inheritance + +For example, a user entity might have profile, preferences, and authentication components. + +### How can I improve database performance? + +- For **PostgreSQL**: + + - Ensure the pgvector extension is properly installed + - Index frequently queried fields + - Use connection pooling + - Consider partitioning for large datasets + +- For **PGLite**: + - Keep database size reasonable (under 1GB) + - Regularly clean up old memories + - Limit the number of concurrent operations + +### Will other database adapters be supported in the future? + +Yes, future releases will add support for additional databases such as: + +- MongoDB +- SQLite +- Supabase +- Qdrant +- SQL + +The adapter interface is designed to be extensible to support a wide range of storage solutions. + +## Further Reading + +- [Memory Management](../guides/memory-management.md) +- [Entity System](./entities.md) +- [Agent Runtime](./agents.md) +```` + +## File: packages/docs/docs/core/knowledge.md +````markdown +# Knowledge Management in ElizaOS + +## Overview + +The Knowledge Management system in ElizaOS is a powerful Retrieval-Augmented Generation (RAG) feature that enables agents to process, store, and retrieve information from various sources. This allows agents to provide contextually relevant responses by leveraging stored knowledge during conversations. + +## Adding Knowledge to Agents + +ElizaOS provides multiple ways to add knowledge to your agents, both during initialization and at runtime. + +### Adding Knowledge During Runtime Creation + +#### 1. Via Character Definition + +The simplest approach is to define knowledge directly in your character configuration: + +```typescript +const character: Character = { + name: 'My Agent', + // Other character properties... + knowledge: [ + // Direct string knowledge + 'Important fact: ElizaOS supports multiple knowledge formats', + + // File references + { path: 'knowledge/documentation.md', shared: false }, + + // Directory references + { directory: 'knowledge/guides', shared: true }, + ], +}; +``` + +The knowledge array supports three formats: + +- String literals for direct knowledge +- File objects pointing to specific files +- Directory objects for entire folders of content + +#### 2. Programmatically Before Runtime Initialization + +You can dynamically load knowledge before creating your runtime: + +```typescript +// Load knowledge from files or other sources +const knowledge = []; + +// Example: Recursively load documentation files +function loadDocumentation(directoryPath) { + const files = getFilesRecursively(directoryPath, ['.md']); + return files.map((filePath) => { + const relativePath = path.relative(basePath, filePath); + const content = fs.readFileSync(filePath, 'utf-8'); + return `Path: ${relativePath}\n\n${content}`; + }); +} + +// Load documentation +const docKnowledge = loadDocumentation('./docs'); +knowledge.push(...docKnowledge); + +// Then include in your character definition +const character: Character = { + // Other character properties... + knowledge: knowledge, +}; +``` + +### Adding Knowledge After Runtime Creation + +#### 1. Using the `addKnowledge` Method + +Add knowledge programmatically after the runtime is initialized: + +```typescript +// Import needed utilities +import { createUniqueUuid } from '@elizaos/core'; + +// Create a knowledge item +const knowledgeItem = { + id: createUniqueUuid(runtime, 'unique-knowledge-identifier'), + content: { + text: 'Important information the agent should know...', + }, +}; + +// Add to runtime with default chunking settings +await runtime.addKnowledge(knowledgeItem); + +// Or with custom chunking settings +await runtime.addKnowledge(knowledgeItem, { + targetTokens: 1500, // Target chunk size (default: 3000) + overlap: 100, // Overlap between chunks (default: 200) + modelContextSize: 8192, // Context size of your model (default: 4096) +}); +``` + +#### 2. Processing Files at Runtime + +You can dynamically process files at runtime: + +```typescript +// For PDF files, use the PDF service +const pdfService = runtime.getService('pdf'); +if (pdfService) { + const pdfBuffer = fs.readFileSync('./knowledge/document.pdf'); + const textContent = await pdfService.convertPdfToText(pdfBuffer); + + const knowledgeItem = { + id: createUniqueUuid(runtime, 'document.pdf'), + content: { text: textContent }, + }; + + await runtime.addKnowledge(knowledgeItem); +} +``` + +## Directory Structure + +ElizaOS expects knowledge files to be organized in the following structure: + +``` +knowledge/ # Root knowledge directory +├── shared/ # Shared knowledge accessible to all agents +└── {agent-name}/ # Agent-specific knowledge directories +``` + +## Supported File Types + +- PDF files (`.pdf`) +- Markdown files (`.md`) +- Text files (`.txt`) + +## Knowledge Modes + +ElizaOS supports two knowledge modes: + +### Classic Mode (Default) + +- Direct string knowledge added to character's context +- No chunking or semantic search +- Enabled by default (`settings.ragKnowledge: false`) +- Only processes string knowledge entries +- Simpler but less sophisticated + +### RAG Mode + +- Advanced knowledge processing with semantic search +- Chunks content and uses embeddings +- Must be explicitly enabled (`settings.ragKnowledge: true`) +- Supports three knowledge types: + 1. Direct string knowledge + 2. Single file references: `{ "path": "path/to/file.md", "shared": false }` + 3. Directory references: `{ "directory": "knowledge/dir", "shared": false }` +- Supported file types: .md, .txt, .pdf +- Optional `shared` flag for knowledge reuse across characters + +To enable RAG mode, add this to your character settings: + +```typescript +const character: Character = { + // Other character properties... + settings: { + ragKnowledge: true, + }, +}; +``` + +## How Knowledge Processing Works + +### Document Processing Flow + +The RAG system processes documents through several stages: + +1. **Directory Processing** + + - The system scans configured directories in `knowledge/` + - Files are processed based on their shared/private status and file type + +2. **File Processing Pipeline** + + - **Preprocessing**: Reading, cleaning, and normalizing text + - **Document-level Processing**: Generating embeddings for the entire document + - **Chunk Processing**: Splitting content into manageable chunks and generating embeddings for each + +3. **Retrieval Process** + - When a user message is received, its embedding is generated + - This embedding is compared to stored knowledge embeddings + - The most semantically similar chunks are retrieved + - Retrieved knowledge is incorporated into the agent's context + +This multi-level approach enables: + +- Broad document-level semantic search +- Fine-grained chunk-level retrieval for specific information +- Efficient parallel processing of large documents +- Maintenance of document context through metadata linking + +### Knowledge Processing Flow Diagram + +```mermaid +graph TB + subgraph Directory_Processing + A[Read Files from Directory] --> B[File Content] + end + + subgraph Preprocessing + B --> C[Clean & Normalize Text] + end + + subgraph Document_Processing + C --> D[Generate Document Embedding] + D --> E[Store Full Document] + E --> |Metadata| F[File Path] + E --> |Metadata| G[File Type] + E --> |Metadata| H[Shared Status] + end + + subgraph Chunk_Processing + C --> I[Split into Chunks] + I --> |512 tokens| J[Chunk 1] + I --> |20 token overlap| K[...] + I --> L[Chunk N] + + subgraph Parallel_Processing + J --> M1[Generate Embedding] + K --> M2[Generate Embedding] + L --> M3[Generate Embedding] + end + + subgraph Chunk_Storage + M1 --> N1[Store Chunk] + M2 --> N2[Store Chunk] + M3 --> N3[Store Chunk] + + N1 --> |Metadata| O[Original Doc Reference] + N1 --> |Metadata| P[Chunk Index] + N2 --> |Metadata| O + N2 --> |Metadata| P + N3 --> |Metadata| O + N3 --> |Metadata| P + end + end + + style Directory_Processing fill:#f9f,stroke:#333,stroke-width:2px + style Preprocessing fill:#bbf,stroke:#333,stroke-width:2px + style Document_Processing fill:#bfb,stroke:#333,stroke-width:2px + style Chunk_Processing fill:#fbf,stroke:#333,stroke-width:2px + style Parallel_Processing fill:#fbb,stroke:#333,stroke-width:2px + style Chunk_Storage fill:#bff,stroke:#333,stroke-width:2px +``` + +### Processing Parameters + +- **Chunk Size**: 512 tokens (default, configurable when adding knowledge) +- **Chunk Overlap**: 20 tokens (default, configurable) +- **Processing Batch Size**: 10 chunks processed concurrently +- **Default Similarity Threshold**: 0.85 for retrieval +- **Default Match Count**: 5 results returned + +## Best Practices for Knowledge Management + +### Content Organization + +1. **Document Structure** + + - Use clear section headings and hierarchical organization + - Break large documents into logical smaller files + - Include metadata and context in markdown files + - Structure information from general to specific + +2. **File Management** + + - Use descriptive filenames that reflect content + - Group related files in subdirectories + - Keep paths short and meaningful + - Avoid special characters in filenames + +3. **Knowledge Optimization** + - Keep individual documents focused on specific topics + - For very detailed information, use smaller chunks (200-300 tokens) by setting `targetTokens` + - Balance the total number of knowledge items for performance + - Prefer markdown (.md) files for best processing results + +### Processing Large Knowledge Bases + +When adding many knowledge items at once, consider implementing a semaphore pattern: + +```typescript +import { Semaphore } from '@elizaos/core'; + +// Create semaphore to limit concurrent processing +const semaphore = new Semaphore(10); + +// Process items with controlled concurrency +await Promise.all( + items.map(async (item) => { + await semaphore.acquire(); + try { + await runtime.addKnowledge(item); + } finally { + semaphore.release(); + } + }) +); +``` + +### Knowledge ID Management + +When adding knowledge programmatically, use consistent ID generation: + +```typescript +import { createUniqueUuid } from '@elizaos/core'; +const knowledgeId = createUniqueUuid(runtime, 'my-content'); +``` + +This ensures deterministic IDs that remain stable across sessions. + +## Troubleshooting + +### Common Issues and Solutions + +1. **Knowledge Not Being Retrieved**: + + - Verify the file is in a supported format (PDF, MD, TXT) + - Check if embeddings were properly generated + - Ensure similarity threshold isn't too high (default: 0.85) + - Test retrieval with more specific queries + - Verify RAG mode is enabled if using file/directory references + +2. **Poor Quality Retrievals**: + + - Break down large documents into smaller, focused files + - Ensure document content is clear and well-structured + - Review the chunking size and overlap settings + - Check if the query contains too many common words + +3. **Performance Issues**: + + - Monitor the total number of knowledge items + - Consider reducing the match count for faster retrieval + - Check embedding processing time for large documents + - Use shared knowledge efficiently across agents + +4. **File Processing Errors**: + - Verify file permissions + - Check if paths are correctly structured + - Ensure PDF files are readable and not password-protected + - Validate that text encoding is UTF-8 + +## Technical Implementation Details + +### Knowledge ID Relationships + +The RAG system uses a hierarchical ID structure to maintain relationships: + +```mermaid +classDiagram + class Document { + +UUID id + +String filePath + +String fileType + +Boolean isShared + +Float32Array embedding + +String content + } + + class Fragment { + +UUID id + +UUID originalId + +Number chunkIndex + +String content + +Float32Array embedding + +String originalPath + } + + Document "1" --> "*" Fragment : generates +``` + +#### ID Generation and Linking + +Documents IDs are generated using `createUniqueUuid(runtime, path, isShared)`, making them deterministic. Fragment IDs follow the format `${documentId}-chunk-${index}` to maintain the relationship to their source document. + +## API Reference + +### Key Methods + +#### `runtime.addKnowledge(item: KnowledgeItem, options?): Promise` + +Adds new knowledge to the agent. + +- Parameters: + - `item`: A knowledge item containing: + - `id`: UUID + - `content`: Object with `text` property + - `options`: Optional processing configuration: + - `targetTokens`: Number (default: 3000) + - `overlap`: Number (default: 200) + - `modelContextSize`: Number (default: 4096) + +#### `runtime.getKnowledge(message: Memory): Promise` + +Retrieves knowledge based on a message's content. + +- Parameters: + - `message`: Memory object containing user message +- Returns: Array of matching KnowledgeItem objects + +### Knowledge Item Definition + +```typescript +interface KnowledgeItem { + id: UUID; + content: { + text: string; + // Optional additional metadata + [key: string]: any; + }; +} +``` + +## Security Considerations + +1. **Access Control**: + + - Use the `shared` flag appropriately to control document access + - Keep sensitive information in agent-specific directories + - Regularly audit knowledge access patterns + +2. **Data Privacy**: + - Do not store sensitive personal information in knowledge files + - Review documents for potentially sensitive content before adding + - Implement appropriate backup and recovery procedures + +## Future Considerations + +1. **Scalability**: + + - Monitor knowledge base size and performance + - Plan for regular maintenance and cleanup + - Consider implementing document versioning + +2. **Integration**: + - Document integration points with other systems + - Plan for potential future file format support + - Consider implementing knowledge base analytics + +## Support and Resources + +- Review the implementation in `packages/core/src/ragknowledge.ts` +- Check the issue tracker for known issues and solutions +- Contribute improvements and bug fixes through pull requests +```` + +## File: packages/docs/docs/core/overview.md +````markdown +--- +sidebar_position: 1 +--- + +# Overview + +ElizaOS is a framework for creating AI agents that can interact across multiple platforms through a consistent, extensible architecture. + +## Core Features + +- **Modular Architecture**: A plugin-based system for extending functionality +- **Entity-Component System**: Flexible data modeling for agents and users +- **Vector-Based Memory**: Semantic retrieval of conversations and knowledge +- **Multi-Modal Interactions**: Support for text, voice, images, and other media formats +- **Reflection & Self-Improvement**: Agents learn from interactions and adapt over time +- **Cross-Platform Integration**: Connect to multiple services through a unified interface + +## Key Components + +ElizaOS consists of these core architectural components: + +[![](/img/architecture.png)](/img/architecture.png) + +### [Agent Runtime](./agents.md) + +The Agent Runtime is the central nervous system of ElizaOS. It orchestrates all components, manages state, processes messages, and coordinates the agent's behavior. + +**Responsibilities:** + +- Lifecycle management +- Service coordination +- Memory management +- State composition +- Action execution +- Model integration + +### [Projects](./project.md) + +Projects are the top-level containers that define one or more agents, their configurations, and shared resources. A project: + +- Defines agent characters and behavior +- Configures plugins and services +- Sets up knowledge and memory systems +- Establishes shared worlds and environments + +### [Entities & Components](./entities.md) + +ElizaOS uses an entity-component architecture for flexible data modeling: + +- **Entities**: Base objects with unique identifiers (agents, users, etc.) +- **Components**: Modular data attached to entities (profiles, settings, etc.) + +This architecture allows for dynamic composition of objects and extensible data models without complex inheritance hierarchies. + +### [Services](./services.md) + +Services connect agents to different platforms (Discord, X/Twitter, Telegram, etc.) and provide specialized capabilities: + +- **Platform Services**: Connect to external platforms +- **Core Services**: Provide essential functionality (speech, vision, etc.) +- **Extension Services**: Add specialized capabilities + +Services use a consistent interface but can provide platform-specific features when needed. + +### [Actions](./actions.md) + +Actions define how agents respond to messages and interact with the world: + +- **Communication Actions**: Generate responses and engage in conversation +- **Integration Actions**: Interact with external systems and APIs +- **Media Actions**: Generate and process images, audio, and other media +- **Platform Actions**: Leverage platform-specific features + +Each action includes validation logic, a handler function, and thought processes that explain the agent's reasoning. + +### [Providers](./providers.md) + +Providers supply contextual information to agents as they make decisions: + +- **Memory Providers**: Access relevant conversation history +- **Knowledge Providers**: Supply factual information +- **State Providers**: Provide current context and environment details +- **Temporal Providers**: Manage time-based awareness + +Providers are dynamically composed to create a comprehensive context for agent decision-making. + +### [Evaluators](./evaluators.md) + +Evaluators analyze conversations after they happen, helping agents learn and improve: + +- **Reflection Evaluator**: Enables self-awareness and improvement +- **Fact Evaluator**: Extracts factual information from conversations +- **Goal Evaluator**: Tracks progress on objectives +- **Relationship Evaluator**: Models connections between entities + +Evaluators create a feedback loop for continuous agent improvement. + +### [Plugins](./plugins.md) + +Plugins extend ElizaOS with new capabilities by adding services, actions, providers, evaluators, and more: + +- **Core Plugins**: Essential functionality for all agents +- **Platform Plugins**: Integrations with external platforms +- **Capability Plugins**: Special abilities like blockchain interaction +- **Utility Plugins**: Tools for specific tasks or domains + +Plugins use a consistent installation and configuration pattern. + +## Data Systems + +### [Database System](./database.md) + +ElizaOS uses a flexible adapter-based database system: + +- **Entity Storage**: Manages entity and component data +- **Memory System**: Stores conversations and extracted facts +- **Vector Search**: Enables semantic retrieval of information +- **Relationship Tracking**: Maps connections between entities +- **World & Room Management**: Organizes conversation spaces + +The current implementation supports PGLite (for development) and PostgreSQL (for production) using Drizzle ORM. + +### [Knowledge System](./knowledge.md) + +The knowledge system enables agents to access and use structured information: + +- **Document Processing**: Converts various file formats into usable knowledge +- **RAG Implementation**: Retrieval-Augmented Generation for contextual responses +- **Semantic Search**: Finds relevant information through vector similarity +- **Memory Integration**: Combines knowledge with conversation memory + +## Structural Elements + +### [Worlds](./worlds.md) + +Worlds are containers for agents, rooms, and shared resources that provide: + +- Namespace isolation +- Resource sharing +- Multi-agent environments +- Context boundaries + +### [Rooms](./rooms.md) + +Rooms are conversation spaces where entities interact: + +- Direct messages between entities +- Group conversations +- Platform-specific channels +- Persistent conversation history + +### [Tasks](./tasks.md) + +The task system enables asynchronous processing and scheduled operations: + +- Background processing +- Scheduled activities +- Workflow management +- Event-driven operations + +## System Flow + +When a message is received: + +1. The **Service** receives the input and forwards it to the **Runtime** +2. The **Runtime** loads the agent configuration from the **Project** +3. **Providers** supply context (memories, knowledge, state) +4. Valid **Actions** are identified through validation functions +5. The agent decides on a response, including internal **thoughts** +6. The response is returned through the **Service** +7. **Evaluators** analyze the conversation for insights +8. New memories and relationships are stored in the **Database** + +This creates a continuous cycle of interaction, reflection, and improvement. + +## Common Patterns + +### Creating an Agent Response + +```typescript +// The agent runtime processes a message and generates a response +const result = await runtime.processMessage({ + entityId: senderId, + roomId: channelId, + content: { text: 'Hello, how are you?' }, +}); + +// The response includes thought process and actions +console.log(result.thought); // Internal reasoning (not shown to user) +console.log(result.text); // The actual response +console.log(result.actions); // Actions performed +``` + +### Storing and Retrieving Memories + +```typescript +// Store a memory +await runtime.createMemory( + { + entityId: userId, + roomId: channelId, + content: { text: 'Important information' }, + embedding: await runtime.useModel(ModelType.TEXT_EMBEDDING, { + text: 'Important information', + }), + }, + 'facts' +); + +// Retrieve relevant memories +const memories = await runtime.searchMemories({ + tableName: 'messages', + roomId: channelId, + embedding: embedding, + count: 5, +}); +``` + +### Creating a Relationship Between Entities + +```typescript +// Establish a relationship +await runtime.createRelationship({ + sourceEntityId: userEntityId, + targetEntityId: agentEntityId, + tags: ['friend', 'frequent_interaction'], + metadata: { + interactions: 12, + trust_level: 'high', + }, +}); +``` + +## FAQ + +### What's the difference between Actions, Evaluators, and Providers? + +**Actions** define what an agent can do and are executed during response generation. **Evaluators** analyze conversations after they happen to extract insights and improve future responses. **Providers** supply contextual information before the agent decides how to respond. + +### How do agent thoughts relate to evaluator reflections? + +Agent **thoughts** are generated during response creation to explain reasoning in the moment. Evaluator **reflections** happen after responses, analyzing longer-term patterns and extracting insights for future interactions. + +### How is memory organized in ElizaOS? + +Memory is organized into different types (messages, facts, knowledge) and stored with vector embeddings for semantic search. This allows agents to retrieve relevant memories based on context rather than just recency. + +### How does the entity-component system work? + +The entity-component system provides a flexible way to model data. **Entities** are base objects with unique IDs, while **Components** are pieces of data attached to entities. This allows for dynamic composition without complex inheritance. + +### How do I extend an agent with new capabilities? + +Create or install plugins that provide new actions, services, providers, or evaluators. Plugins can be registered in the project configuration and will be automatically loaded when the agent starts. + +### What model providers are supported? + +ElizaOS supports multiple model providers including OpenAI, Anthropic, and local models. The model provider is configured at the project level and can be overridden for specific operations. + +### How do I configure the database? + +ElizaOS currently supports PostgreSQL (recommended for production) and PGLite (for development). Configure the connection using environment variables like `POSTGRES_URL` or `PGLITE_DATA_DIR`. + +### How do services differ from the old "clients"? + +Services provide a more comprehensive integration model than the previous "clients" concept. They offer standardized interfaces for various platforms while allowing for platform-specific features and optimizations. + +## Getting Started + +To create your first ElizaOS project, see the [Quick Start Guide](../quickstart.md) +```` + +## File: packages/docs/docs/quickstart.md +````markdown +--- +sidebar_position: 2 +--- + +# Quickstart Guide + +--- + +## 1. Simple Start - Get Running Quickly + +The fastest way to get started with ElizaOS is using the CLI: + +```bash +# Install globally (optional but recommended) +npm install -g @elizaos/cli + +# Or use directly with npx +npx elizaos start +``` + +This will: + +1. Start ElizaOS with default settings +2. Load the default character +3. Make the agent accessible via terminal and REST API + +### Chat with your agent: + +Visit https://localhost:3000 to interact with your agent through a web interface. + +## 2. Creating a Project + +If you want to create a custom ElizaOS project with your own characters and configurations: + +```bash +# Create a new project with the interactive wizard +npx elizaos create + +# Or specify project type directly +npx elizaos create --type project +``` + +Follow the interactive prompts to configure your project. Once created: + +```bash +# Navigate to your project directory +cd my-project-name + +# Start your project +npx elizaos start +``` + +### Add plugins to your project: + +```bash +# List available plugins +npx elizaos project list-plugins + +# Add a plugin +npx elizaos project add-plugin @elizaos/plugin-discord +``` + +## 3. Creating a Plugin + +Want to extend ElizaOS with custom functionality? + +```bash +# Create a new plugin project +npx elizaos create --type plugin + +# Follow the interactive prompts +``` + +Develop your plugin following the structure in your generated project: + +```bash +# Test your plugin +npx elizaos start + +# Publish your plugin when ready +npx elizaos plugin publish +``` + +### Publishing options: + +```bash +# Test publish without making changes +npx elizaos plugin publish --test + +# Publish to npm +npx elizaos plugin publish --npm + +# Specify platform compatibility +npx elizaos plugin publish --platform node +``` + +## 4. Contributing to ElizaOS + +If you want to add features or fix bugs in the ElizaOS core: + +```bash +# Clone the repository +git clone git@github.com:elizaOS/eliza.git +cd eliza + +# Switch to development branch +git checkout develop + +# Install dependencies +bun install + +# Build the project +bun build + +# Start ElizaOS +bun start +``` + +Visit https://localhost:3000 to interact with your agent through a web interface. + +### Automated setup: + +```bash +git clone git@github.com:elizaOS/eliza.git +cd eliza + +# Run the start script with verbose logging +./scripts/start.sh -v +``` + +--- + +## Troubleshooting + +
+Common Issues + +### Node Version + +- Use Node 23.3.0+ (`node -v` to check) +- Try using NVM: `nvm use 23` + +### Installation Problems + +```bash +# Clean and reinstall +bun clean +bun install --no-frozen-lockfile +bun build +``` + +### Plugin Issues + +```bash +# Rebuild problematic packages +bun rebuild better-sqlite3 +``` + +### Docker Issues + +```bash +# Clean up Docker environment +docker rmi -f $(docker images -aq) +docker builder prune -a -f +``` + +
+ +--- + +## Next Steps + +Once you have your agent running, explore: + +1. 🤖 [Understand Agents](./core/agents.md) +2. 📝 [Create Custom Characters](./core/characterfile.md) +3. ⚡ [Add Custom Actions](./core/actions.md) +4. 🔧 [Advanced Configuration](./guides/configuration.md) + +Join the [Discord community](https://discord.gg/elizaOS) for support and to share what you're building! +```` + +## File: .env.example +```` +# OpenAI Configuration +OPENAI_API_KEY= + +# Anthropic Configuration +ANTHROPIC_API_KEY= + +# Fill these out if you want to use Discord +DISCORD_APPLICATION_ID= +DISCORD_API_TOKEN= + +# Fill these out if you want to use Postgres +POSTGRES_URL= + +# Fill these out if you want to use Telegram +TELEGRAM_BOT_TOKEN= + +# Fill these out if you want to use Twitter +TWITTER_USERNAME= +TWITTER_PASSWORD= +TWITTER_EMAIL= + +# Fill these out if you want to use EVM +EVM_PRIVATE_KEY= +EVM_CHAINS=mainnet,sepolia,base,arbitrum,polygon +EVM_PROVIDER_URL= + +# Fill these out if you want to use Solana +SOLANA_PUBLIC_KEY= +SOLANA_PRIVATE_KEY= +BIRDEYE_API_KEY= + +# Local AI Configuration +USE_LOCAL_AI= +USE_STUDIOLM_TEXT_MODELS= +USE_OLLAMA_TEXT_MODELS= + +# Ollama Configuration +OLLAMA_SERVER_URL= +OLLAMA_MODEL= +USE_OLLAMA_EMBEDDING= +OLLAMA_EMBEDDING_MODEL= +SMALL_OLLAMA_MODEL= +MEDIUM_OLLAMA_MODEL= +LARGE_OLLAMA_MODEL= + +# StudioLM Configuration +STUDIOLM_SERVER_URL= +STUDIOLM_SMALL_MODEL= +STUDIOLM_MEDIUM_MODEL= +STUDIOLM_EMBEDDING_MODEL= + +# Settings for The Org + +COMMUNITY_MANAGER_DISCORD_APPLICATION_ID= +COMMUNITY_MANAGER_DISCORD_API_TOKEN= + +SOCIAL_MEDIA_MANAGER_DISCORD_APPLICATION_ID= +SOCIAL_MEDIA_MANAGER_DISCORD_API_TOKEN= + +LIAISON_DISCORD_APPLICATION_ID= +LIAISON_DISCORD_API_TOKEN= + +PROJECT_MANAGER_DISCORD_APPLICATION_ID= +PROJECT_MANAGER_DISCORD_API_TOKEN= + +DEV_REL_DISCORD_APPLICATION_ID= +DEV_REL_DISCORD_API_TOKEN= +DEVREL_IMPORT_KNOWLEDGE=true + +INVESTMENT_MANAGER_DISCORD_APPLICATION_ID= +INVESTMENT_MANAGER_DISCORD_API_TOKEN= + +# Settings for Investment Manager plugins +BIRDEYE_API_KEY= +JUPITER_API_KEY= +HELIUS_API_KEY= +COINMARKETCAP_API_KEY= +ZEROEX_API_KEY= +COINGECKO_API_KEY= +```` + +## File: package.json +````json +{ + "name": "eliza", + "scripts": { + "preinstall": "only-allow bun", + "start": "cd ./packages/the-org && bun run start", + "start:debug": "LOG_LEVEL=debug elizaos start", + "start:app": "turbo run start --filter=./packages/app", + "dev": "turbo run dev --filter=./packages/the-org", + "build:docs": "turbo run build --filter=@elizaos/docs", + "build": "turbo run build --filter=@elizaos/client && turbo run build --filter=!@elizaos/docs", + "clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo bun.lock* && turbo run clean --filter=./packages/*", + "lint": "turbo run lint --filter=./packages/* && prettier --write . && prettier --check .", + "pre-commit": "bun run scripts/pre-commit-lint", + "release": "bun run build && bun lint && lerna publish --no-private --force-publish && bun lint", + "release:alpha": "lerna publish prerelease --preid alpha --dist-tag alpha --no-private --force-publish --loglevel verbose", + "migrate": "turbo run migrate --filter=./packages/plugin-sql --force", + "migrate:generate": "turbo run migrate:generate --filter=./packages/plugin-sql", + "docker:build": "bash ./scripts/docker.sh build", + "docker:run": "bash ./scripts/docker.sh run", + "docker:bash": "bash ./scripts/docker.sh bash", + "docker:start": "bash ./scripts/docker.sh start", + "docker": "bun docker:build && bun docker:run && bun docker:bash", + "test": "turbo run test --concurrency 20 --filter=!./packages/plugin-starter --filter=!./packages/project-starter --filter=!./packages/the-org --filter=!./packages/docs --filter=!./packages/plugin-video-understanding", + "test:app": "turbo run test --concurrency 20 --filter=./packages/app", + "prepare": "husky" + }, + "devDependencies": { + "@types/bun": "latest", + "@types/node": "^22.13.10", + "@types/uuid": "^9.0.8", + "@vitest/eslint-plugin": "1.0.1", + "bun": "1.2.5", + "concurrently": "9.1.0", + "cross-env": "7.0.3", + "husky": "^9.1.7", + "lerna": "8.1.4", + "lint-staged": "^15.5.0", + "only-allow": "^1.2.1", + "sharp": "0.33.5", + "tsup": "8.4.0", + "turbo": "^2.4.4", + "typedoc": "0.27.9", + "typescript": "5.8.2", + "vite": "5.4.12", + "vitest": "3.0.5" + }, + "bun": { + "overrides": { + "cookie": "0.7.0", + "bs58": "5.0.0", + "secp256k1": "5.0.1", + "minipass": "7.1.2", + "form-data": "4.0.2", + "eslint": "9.22.0", + "react": "19.0.0", + "react-dom": "19.0.0", + "got": "12.6.1" + } + }, + "engines": { + "node": "23.3.0" + }, + "dependencies": { + "@anthropic-ai/sdk": "^0.39.0", + "@babel/generator": "^7.26.9", + "vittest": "^1.0.2", + "zod": "3.24.1" + }, + "packageManager": "bun@1.2.5", + "workspaces": [ + "packages/*" + ], + "module": "index.ts", + "type": "module", + "resolutions": { + "@nrwl/devkit": "19.8.13", + "@nrwl/tao": "19.8.13", + "zod": "3.24.1", + "eslint": "9.22.0", + "react": "19.0.0", + "react-dom": "19.0.0", + "vitest": "3.0.5", + "@metaplex-foundation/umi": "0.9.2", + "typedoc-plugin-markdown": "4.2.10", + "buffer": "6.0.3", + "@solana/spl-token": "0.4.9", + "solana-bankrun": "0.3.1", + "got": "12.6.1", + "form-data": "4.0.2" + }, + "trustedDependencies": [ + "@swc/core", + "bigint-buffer", + "bufferutil", + "bun", + "canvas", + "esbuild", + "husky", + "node-llama-cpp", + "protobufjs", + "sharp", + "utf-8-validate" + ] +} +```` + +## File: README.md +````markdown +# Eliza 🤖 + +
+ Eliza Banner +
+ +
+ +📑 [Technical Report](https://arxiv.org/pdf/2501.06781) | 📖 [Documentation](https://elizaos.github.io/eliza/) | 🎯 [Examples](https://github.com/thejoven/awesome-eliza) + +
+ +## 🌍 README Translations + +[中文说明](packages/docs/i18n/readme/README_CN.md) | [日本語の説明](packages/docs/i18n/readme/README_JA.md) | [한국어 설명](packages/docs/i18n/readme/README_KOR.md) | [Persian](packages/docs/i18n/readme/README_FA.md) | [Français](packages/docs/i18n/readme/README_FR.md) | [Português](packages/docs/i18n/readme/README_PTBR.md) | [Türkçe](packages/docs/i18n/readme/README_TR.md) | [Русский](packages/docs/i18n/readme/README_RU.md) | [Español](packages/docs/i18n/readme/README_ES.md) | [Italiano](packages/docs/i18n/readme/README_IT.md) | [ไทย](packages/docs/i18n/readme/README_TH.md) | [Deutsch](packages/docs/i18n/readme/README_DE.md) | [Tiếng Việt](packages/docs/i18n/readme/README_VI.md) | [עִברִית](packages/docs/i18n/readme/README_HE.md) | [Tagalog](packages/docs/i18n/readme/README_TG.md) | [Polski](packages/docs/i18n/readme/README_PL.md) | [Arabic](packages/docs/i18n/readme/README_AR.md) | [Hungarian](packages/docs/i18n/readme/README_HU.md) | [Srpski](packages/docs/i18n/readme/README_RS.md) | [Română](packages/docs/i18n/readme/README_RO.md) | [Nederlands](packages/docs/i18n/readme/README_NL.md) | [Ελληνικά](packages/docs/i18n/readme/README_GR.md) + +## 🚩 Overview + +
+ Eliza Diagram +
+ +## ✨ Features + +- 🛠️ Full-featured Discord, X (Twitter) and Telegram connectors +- 🔗 Support for every model (Llama, Grok, OpenAI, Anthropic, Gemini, etc.) +- 👥 Multi-agent and room support +- 📚 Easily ingest and interact with your documents +- 💾 Retrievable memory and document store +- 🚀 Highly extensible - create your own actions and clients +- 📦 Just works! + +## Video Tutorials + +[AI Agent Dev School](https://www.youtube.com/watch?v=ArptLpQiKfI&list=PLx5pnFXdPTRzWla0RaOxALTSTnVq53fKL) + +## 🎯 Use Cases + +- 🤖 Chatbots +- 🕵️ Autonomous Agents +- 📈 Business Process Handling +- 🎮 Video Game NPCs +- 🧠 Trading + +## 🚀 Quick Start + +### Prerequisites + +- [Python 2.7+](https://www.python.org/downloads/) +- [Node 23+](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) +- [bun](https://bun.io/installation) + +> **Note for Windows Users:** [WSL 2](https://learn.microsoft.com/en-us/windows/wsl/install-manual) is required. + +### Use the Starter (Recommended) + +```bash +git clone https://github.com/elizaos/eliza-starter.git +cd eliza-starter +cp .env.example .env +bun i && bun run build && bun start +``` + +### Manually Start Eliza (Only recommended if you know what you are doing) + +#### Checkout the latest release + +```bash +# Clone the repository +git clone https://github.com/elizaos/eliza.git + +# This project iterates fast, so we recommend checking out the latest release +git checkout $(git describe --tags --abbrev=0) +# If the above doesn't checkout the latest release, this should work: +# git checkout $(git describe --tags `git rev-list --tags --max-count=1`) +``` + +#### Edit the .env file + +Copy .env.example to .env and fill in the appropriate values. + +``` +cp .env.example .env +``` + +Note: .env is optional. If you're planning to run multiple distinct agents, you can pass secrets through the character JSON + +#### Start Eliza + +Important! We now use Bun. If you are using npm, you will need to install Bun: +https://bun.sh/docs/installation + +```bash +bun install +bun run build # npm will work too +bun start # npm will work too +``` + +### Interact via Browser + +Once the agent is running, you can visit http://localhost:3000 to interact with your agent through a web interface. The interface provides: + +- Real-time chat with your agent +- Character configuration options +- Plugin management +- Memory and conversation history + +--- + +### Automatically Start Eliza + +The start script provides an automated way to set up and run Eliza: + +## Citation + +We now have a [paper](https://arxiv.org/pdf/2501.06781) you can cite for the Eliza OS: + +```bibtex +@article{walters2025eliza, + title={Eliza: A Web3 friendly AI Agent Operating System}, + author={Walters, Shaw and Gao, Sam and Nerd, Shakker and Da, Feng and Williams, Warren and Meng, Ting-Chien and Han, Hunter and He, Frank and Zhang, Allen and Wu, Ming and others}, + journal={arXiv preprint arXiv:2501.06781}, + year={2025} +} +``` + +## Contributors + + + Eliza project contributors + + +## Star History + +[![Star History Chart](https://api.star-history.com/svg?repos=elizaos/eliza&type=Date)](https://star-history.com/#elizaos/eliza&Date) + +## Git Hooks + +This project uses git hooks to ensure code quality: + +- **pre-commit**: Automatically formats staged files using Prettier before committing + +To run the pre-commit hook manually: + +```bash +bun run pre-commit +``` +```` + + +# Instruction +# ElizaOS Developer Context + +This file contains the core technical aspects of ElizaOS, focusing on its architecture, implementation, and developer-facing components. The codebase is organized as a monorepo with several key packages: + +## Key Components + +1. **Core Package**: The foundation of ElizaOS with the agent runtime, entity management, actions, and database interactions +2. **CLI Package**: Command-line interface for managing agents, projects, and development tasks +3. **Client Package**: Frontend interface components and API interactions +4. **SQL/Database**: Database adapters and schema management +5. **Autodoc**: Documentation generation tools + +## Technical Goals + +When analyzing this codebase: + +- Focus on the architecture and relationships between components +- Identify core abstractions and design patterns +- Understand the runtime execution flow +- Analyze how agents, actions, and providers work together +- Look for opportunities to improve code organization and performance +- Consider modular extension points and plugin architecture + +## Output Guidance + +- When suggesting improvements, focus on technical aspects like code structure, performance optimizations, and architectural changes +- Include specific code examples when proposing changes +- Consider backwards compatibility and migration paths for any proposed changes +- Highlight innovative technical approaches used in the system +- When asked about implementation details, provide comprehensive technical explanations diff --git a/packages/docs/static/llms.txt b/packages/docs/static/llms.txt new file mode 100644 index 00000000000..a78f588d092 --- /dev/null +++ b/packages/docs/static/llms.txt @@ -0,0 +1,2744 @@ +```bash +bun install +bun run build # npm will work too +bun start # npm will work too +``` + +### Interact via Browser + +Once the agent is running, visit https://localhost:3000 to interact with your agent through a web interface. + +No separate client startup is needed for basic interaction in the newer versions. + +```` + +## File: packages/core/src/types.ts +````typescript +import type { Readable } from "node:stream"; +export type UUID = `${string}-${string}-${string}-${string}-${string}`; +export function asUUID(id: string): UUID +export interface Content { + thought?: string; + text?: string; + actions?: string[]; + providers?: string[]; + source?: string; + url?: string; + inReplyTo?: UUID; + attachments?: Media[]; + [key: string]: unknown; +} +export interface ActionExample { + name: string; + content: Content; +} +export type ModelType = (typeof ModelTypes)[keyof typeof ModelTypes] | string; +⋮---- +export type ServiceType = (typeof ServiceTypes)[keyof typeof ServiceTypes]; +⋮---- +export interface State { + [key: string]: any; + values: { + [key: string]: any; + }; + data: { + [key: string]: any; + }; + text: string; +} +export type MemoryTypeAlias = string; +export enum MemoryType { + DOCUMENT = "document", + FRAGMENT = "fragment", + MESSAGE = "message", + DESCRIPTION = "description", + CUSTOM = "custom", +} +export type MemoryScope = "shared" | "private" | "room"; +export interface BaseMetadata { + type: MemoryTypeAlias; + source?: string; + sourceId?: UUID; + scope?: MemoryScope; + timestamp?: number; + tags?: string[]; +} +export interface DocumentMetadata extends BaseMetadata { + type: MemoryType.DOCUMENT; +} +export interface FragmentMetadata extends BaseMetadata { + type: MemoryType.FRAGMENT; + documentId: UUID; + position: number; +} +export interface MessageMetadata extends BaseMetadata { + type: MemoryType.MESSAGE; +} +export interface DescriptionMetadata extends BaseMetadata { + type: MemoryType.DESCRIPTION; +} +export interface CustomMetadata extends BaseMetadata { + type: MemoryTypeAlias; + [key: string]: unknown; +} +export type MemoryMetadata = + | DocumentMetadata + | FragmentMetadata + | MessageMetadata + | DescriptionMetadata + | CustomMetadata; +export interface Memory { + id?: UUID; + entityId: UUID; + agentId?: UUID; + createdAt?: number; + content: Content; + embedding?: number[]; + roomId: UUID; + unique?: boolean; + similarity?: number; + metadata?: MemoryMetadata; +} +export interface Log { + id?: UUID; + entityId: UUID; + roomId?: UUID; + body: { [key: string]: unknown }; + type: string; + createdAt: Date; +} +export interface MessageExample { + name: string; + content: Content; +} +export type Handler = ( + runtime: IAgentRuntime, + message: Memory, + state?: State, + options?: { [key: string]: unknown }, + callback?: HandlerCallback, + responses?: Memory[] +) => Promise; +export type HandlerCallback = ( + response: Content, + files?: any +) => Promise; +export type Validator = ( + runtime: IAgentRuntime, + message: Memory, + state?: State +) => Promise; +export interface Action { + similes?: string[]; + description: string; + examples?: ActionExample[][]; + handler: Handler; + name: string; + validate: Validator; +} +export interface EvaluationExample { + prompt: string; + messages: Array; + outcome: string; +} +export interface Evaluator { + alwaysRun?: boolean; + description: string; + similes?: string[]; + examples: EvaluationExample[]; + handler: Handler; + name: string; + validate: Validator; +} +export interface ProviderResult { + values?: { + [key: string]: any; + }; + data?: { + [key: string]: any; + }; + text?: string; +} +export interface Provider { + name: string; + description?: string; + dynamic?: boolean; + position?: number; + private?: boolean; + get: ( + runtime: IAgentRuntime, + message: Memory, + state: State + ) => Promise; +} +export interface Relationship { + id: UUID; + sourceEntityId: UUID; + targetEntityId: UUID; + agentId: UUID; + tags: string[]; + metadata: { + [key: string]: any; + }; + createdAt?: string; +} +export interface Component { + id: UUID; + entityId: UUID; + agentId: UUID; + roomId: UUID; + worldId: UUID; + sourceEntityId: UUID; + type: string; + data: { + [key: string]: any; + }; +} +export interface Entity { + id?: UUID; + names: string[]; + metadata?: { [key: string]: any }; + agentId: UUID; + components?: Component[]; +} +export type World = { + id: UUID; + name?: string; + agentId: UUID; + serverId: string; + metadata?: { + ownership?: { + ownerId: string; + }; + roles?: { + [entityId: UUID]: Role; + }; + [key: string]: unknown; + }; +}; +export type Room = { + id: UUID; + name?: string; + agentId?: UUID; + source: string; + type: ChannelType; + channelId?: string; + serverId?: string; + worldId?: UUID; + metadata?: Record; +}; +export interface Participant { + id: UUID; + entity: Entity; +} +export type Media = { + id: string; + url: string; + title: string; + source: string; + description: string; + text: string; + contentType?: string; +}; +export enum ChannelType { + SELF = "SELF", + DM = "DM", + GROUP = "GROUP", + VOICE_DM = "VOICE_DM", + VOICE_GROUP = "VOICE_GROUP", + FEED = "FEED", + THREAD = "THREAD", + WORLD = "WORLD", + API = "API", + FORUM = "FORUM", +} +export abstract class Service +⋮---- +constructor(runtime?: IAgentRuntime) +abstract stop(): Promise; +⋮---- +static async start(_runtime: IAgentRuntime): Promise +static async stop(_runtime: IAgentRuntime): Promise +⋮---- +export type Route = { + type: "GET" | "POST" | "PUT" | "DELETE" | "STATIC"; + path: string; + filePath?: string; + handler?: (req: any, res: any, runtime: IAgentRuntime) => Promise; +}; +export interface Plugin { + name: string; + description: string; + init?: ( + config: Record, + runtime: IAgentRuntime + ) => Promise; + config?: { [key: string]: any }; + memoryManagers?: IMemoryManager[]; + services?: (typeof Service)[]; + componentTypes?: { + name: string; + schema: Record; + validator?: (data: any) => boolean; + }[]; + actions?: Action[]; + providers?: Provider[]; + evaluators?: Evaluator[]; + adapter?: IDatabaseAdapter; + models?: { + [key: string]: (...args: any[]) => Promise; + }; + events?: { + [K in keyof EventPayloadMap]?: EventHandler[]; + } & { + [key: string]: ((params: EventPayload) => Promise)[]; + }; + routes?: Route[]; + tests?: TestSuite[]; +} +export interface ProjectAgent { + character: Character; + init?: (runtime: IAgentRuntime) => Promise; + plugins?: Plugin[]; + tests?: TestSuite | TestSuite[]; +} +export interface Project { + agents: ProjectAgent[]; +} +export type TemplateType = + | string + | ((options: { state: State | { [key: string]: string } }) => string); +export interface Character { + id?: UUID; + name: string; + username?: string; + system?: string; + templates?: { + [key: string]: TemplateType; + }; + bio: string | string[]; + messageExamples?: MessageExample[][]; + postExamples?: string[]; + topics?: string[]; + adjectives?: string[]; + knowledge?: (string | { path: string; shared?: boolean })[]; + plugins?: string[]; + settings?: { + [key: string]: any | string | boolean | number; + }; + secrets?: { + [key: string]: string | boolean | number; + }; + style?: { + all?: string[]; + chat?: string[]; + post?: string[]; + }; +} +export interface Agent extends Character { + createdAt: number; + updatedAt: number; +} +export interface IDatabaseAdapter { + db: any; + init(): Promise; + close(): Promise; + getAgent(agentId: UUID): Promise; + getAgents(): Promise; + createAgent(agent: Partial): Promise; + updateAgent(agentId: UUID, agent: Partial): Promise; + deleteAgent(agentId: UUID): Promise; + ensureAgentExists(agent: Partial): Promise; + ensureEmbeddingDimension(dimension: number): Promise; + getEntityById(entityId: UUID): Promise; + getEntitiesForRoom( + roomId: UUID, + includeComponents?: boolean + ): Promise; + createEntity(entity: Entity): Promise; + updateEntity(entity: Entity): Promise; + getComponent( + entityId: UUID, + type: string, + worldId?: UUID, + sourceEntityId?: UUID + ): Promise; + getComponents( + entityId: UUID, + worldId?: UUID, + sourceEntityId?: UUID + ): Promise; + createComponent(component: Component): Promise; + updateComponent(component: Component): Promise; + deleteComponent(componentId: UUID): Promise; + getMemories(params: { + roomId: UUID; + count?: number; + unique?: boolean; + tableName: string; + start?: number; + end?: number; + }): Promise; + getMemoryById(id: UUID): Promise; + getMemoriesByIds(ids: UUID[], tableName?: string): Promise; + getMemoriesByRoomIds(params: { + tableName: string; + roomIds: UUID[]; + limit?: number; + }): Promise; + getCachedEmbeddings(params: { + query_table_name: string; + query_threshold: number; + query_input: string; + query_field_name: string; + query_field_sub_name: string; + query_match_count: number; + }): Promise<{ embedding: number[]; levenshtein_score: number }[]>; + log(params: { + body: { [key: string]: unknown }; + entityId: UUID; + roomId: UUID; + type: string; + }): Promise; + getLogs(params: { + entityId: UUID; + roomId?: UUID; + type?: string; + count?: number; + offset?: number; + }): Promise; + deleteLog(logId: UUID): Promise; + searchMemories(params: { + embedding: number[]; + match_threshold?: number; + count?: number; + roomId?: UUID; + unique?: boolean; + tableName: string; + }): Promise; + createMemory( + memory: Memory, + tableName: string, + unique?: boolean + ): Promise; + removeMemory(memoryId: UUID, tableName: string): Promise; + removeAllMemories(roomId: UUID, tableName: string): Promise; + countMemories( + roomId: UUID, + unique?: boolean, + tableName?: string + ): Promise; + createWorld(world: World): Promise; + getWorld(id: UUID): Promise; + getAllWorlds(): Promise; + updateWorld(world: World): Promise; + getRoom(roomId: UUID): Promise; + createRoom({ + id, + name, + source, + type, + channelId, + serverId, + worldId, + }: Room): Promise; + deleteRoom(roomId: UUID): Promise; + updateRoom(room: Room): Promise; + getRoomsForParticipant(entityId: UUID): Promise; + getRoomsForParticipants(userIds: UUID[]): Promise; + getRooms(worldId: UUID): Promise; + addParticipant(entityId: UUID, roomId: UUID): Promise; + removeParticipant(entityId: UUID, roomId: UUID): Promise; + getParticipantsForEntity(entityId: UUID): Promise; + getParticipantsForRoom(roomId: UUID): Promise; + getParticipantUserState( + roomId: UUID, + entityId: UUID + ): Promise<"FOLLOWED" | "MUTED" | null>; + setParticipantUserState( + roomId: UUID, + entityId: UUID, + state: "FOLLOWED" | "MUTED" | null + ): Promise; + createRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + tags?: string[]; + metadata?: { [key: string]: any }; + }): Promise; + updateRelationship(relationship: Relationship): Promise; + getRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + }): Promise; + getRelationships(params: { + entityId: UUID; + tags?: string[]; + }): Promise; + ensureEmbeddingDimension(dimension: number): Promise; + getCache(key: string): Promise; + setCache(key: string, value: T): Promise; + deleteCache(key: string): Promise; + createTask(task: Task): Promise; + getTasks(params: { roomId?: UUID; tags?: string[] }): Promise; + getTask(id: UUID): Promise; + getTasksByName(name: string): Promise; + updateTask(id: UUID, task: Partial): Promise; + deleteTask(id: UUID): Promise; + getMemoryManager( + tableName: string + ): IMemoryManager | null; +} +⋮---- +init(): Promise; +close(): Promise; +getAgent(agentId: UUID): Promise; +getAgents(): Promise; +createAgent(agent: Partial): Promise; +updateAgent(agentId: UUID, agent: Partial): Promise; +deleteAgent(agentId: UUID): Promise; +ensureAgentExists(agent: Partial): Promise; +ensureEmbeddingDimension(dimension: number): Promise; +getEntityById(entityId: UUID): Promise; +getEntitiesForRoom( + roomId: UUID, + includeComponents?: boolean + ): Promise; +createEntity(entity: Entity): Promise; +updateEntity(entity: Entity): Promise; +getComponent( + entityId: UUID, + type: string, + worldId?: UUID, + sourceEntityId?: UUID + ): Promise; +getComponents( + entityId: UUID, + worldId?: UUID, + sourceEntityId?: UUID + ): Promise; +createComponent(component: Component): Promise; +updateComponent(component: Component): Promise; +deleteComponent(componentId: UUID): Promise; +getMemories(params: { + roomId: UUID; + count?: number; + unique?: boolean; + tableName: string; + start?: number; + end?: number; + }): Promise; +getMemoryById(id: UUID): Promise; +getMemoriesByIds(ids: UUID[], tableName?: string): Promise; +getMemoriesByRoomIds(params: { + tableName: string; + roomIds: UUID[]; + limit?: number; + }): Promise; +getCachedEmbeddings(params: { + query_table_name: string; + query_threshold: number; + query_input: string; + query_field_name: string; + query_field_sub_name: string; + query_match_count: number; +}): Promise< +log(params: { + body: { [key: string]: unknown }; + entityId: UUID; + roomId: UUID; + type: string; + }): Promise; +getLogs(params: { + entityId: UUID; + roomId?: UUID; + type?: string; + count?: number; + offset?: number; + }): Promise; +deleteLog(logId: UUID): Promise; +searchMemories(params: { + embedding: number[]; + match_threshold?: number; + count?: number; + roomId?: UUID; + unique?: boolean; + tableName: string; + }): Promise; +createMemory( + memory: Memory, + tableName: string, + unique?: boolean + ): Promise; +removeMemory(memoryId: UUID, tableName: string): Promise; +removeAllMemories(roomId: UUID, tableName: string): Promise; +countMemories( + roomId: UUID, + unique?: boolean, + tableName?: string + ): Promise; +createWorld(world: World): Promise; +getWorld(id: UUID): Promise; +getAllWorlds(): Promise; +updateWorld(world: World): Promise; +getRoom(roomId: UUID): Promise; +createRoom({ + id, + name, + source, + type, + channelId, + serverId, + worldId, + }: Room): Promise; +deleteRoom(roomId: UUID): Promise; +updateRoom(room: Room): Promise; +getRoomsForParticipant(entityId: UUID): Promise; +getRoomsForParticipants(userIds: UUID[]): Promise; +getRooms(worldId: UUID): Promise; +addParticipant(entityId: UUID, roomId: UUID): Promise; +removeParticipant(entityId: UUID, roomId: UUID): Promise; +getParticipantsForEntity(entityId: UUID): Promise; +getParticipantsForRoom(roomId: UUID): Promise; +getParticipantUserState( + roomId: UUID, + entityId: UUID + ): Promise<"FOLLOWED" | "MUTED" | null>; +setParticipantUserState( + roomId: UUID, + entityId: UUID, + state: "FOLLOWED" | "MUTED" | null + ): Promise; +createRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + tags?: string[]; + metadata?: { [key: string]: any }; + }): Promise; +updateRelationship(relationship: Relationship): Promise; +getRelationship(params: { + sourceEntityId: UUID; + targetEntityId: UUID; + }): Promise; +getRelationships(params: { + entityId: UUID; + tags?: string[]; + }): Promise; +⋮---- +getCache(key: string): Promise; +setCache(key: string, value: T): Promise; +deleteCache(key: string): Promise; +createTask(task: Task): Promise; +getTasks(params: +getTask(id: UUID): Promise; +getTasksByName(name: string): Promise; +updateTask(id: UUID, task: Partial): Promise; +deleteTask(id: UUID): Promise; +getMemoryManager( + tableName: string + ): IMemoryManager | null; +⋮---- +export interface EmbeddingSearchResult { + embedding: number[]; + levenshtein_score: number; +} +export interface MemoryRetrievalOptions { + roomId: UUID; + count?: number; + unique?: boolean; + start?: number; + end?: number; + agentId?: UUID; +} +export interface MemorySearchOptions { + embedding: number[]; + match_threshold?: number; + count?: number; + roomId: UUID; + agentId?: UUID; + unique?: boolean; + metadata?: Partial; +} +export interface MultiRoomMemoryOptions { + roomIds: UUID[]; + limit?: number; + agentId?: UUID; +} +export interface UnifiedMemoryOptions { + roomId: UUID; + limit?: number; + agentId?: UUID; + unique?: boolean; + start?: number; + end?: number; +} +export interface UnifiedSearchOptions extends UnifiedMemoryOptions { + embedding: number[]; + similarity?: number; +} +export interface IMemoryManager { + readonly runtime: IAgentRuntime; + readonly tableName: string; + addEmbeddingToMemory(memory: T): Promise; + getMemories( + opts: MemoryRetrievalOptions | UnifiedMemoryOptions + ): Promise; + searchMemories( + params: MemorySearchOptions | UnifiedSearchOptions + ): Promise; + getCachedEmbeddings(content: string): Promise; + getMemoryById(id: UUID): Promise; + getMemoriesByRoomIds(params: MultiRoomMemoryOptions): Promise; + createMemory(memory: T, unique?: boolean): Promise; + removeMemory(memoryId: UUID): Promise; + removeAllMemories(roomId: UUID): Promise; + countMemories(roomId: UUID, unique?: boolean): Promise; +} +⋮---- +addEmbeddingToMemory(memory: T): Promise; +getMemories( + opts: MemoryRetrievalOptions | UnifiedMemoryOptions + ): Promise; +searchMemories( + params: MemorySearchOptions | UnifiedSearchOptions + ): Promise; +getCachedEmbeddings(content: string): Promise; +getMemoryById(id: UUID): Promise; +getMemoriesByRoomIds(params: MultiRoomMemoryOptions): Promise; +createMemory(memory: T, unique?: boolean): Promise; +removeMemory(memoryId: UUID): Promise; +removeAllMemories(roomId: UUID): Promise; +countMemories(roomId: UUID, unique?: boolean): Promise; +⋮---- +export type CacheOptions = { + expires?: number; +}; +export interface IAgentRuntime extends IDatabaseAdapter { + agentId: UUID; + character: Character; + providers: Provider[]; + actions: Action[]; + evaluators: Evaluator[]; + plugins: Plugin[]; + services: Map; + events: Map Promise)[]>; + fetch?: typeof fetch | null; + routes: Route[]; + registerPlugin(plugin: Plugin): Promise; + initialize(): Promise; + getKnowledge(message: Memory): Promise; + addKnowledge( + item: KnowledgeItem, + options: { + targetTokens: number; + overlap: number; + modelContextSize: number; + } + ): Promise; + getMemoryManager( + tableName: string + ): IMemoryManager | null; + getService(service: ServiceType | string): T | null; + getAllServices(): Map; + registerService(service: typeof Service): void; + registerDatabaseAdapter(adapter: IDatabaseAdapter): void; + setSetting( + key: string, + value: string | boolean | null | any, + secret: boolean + ): void; + getSetting(key: string): string | boolean | null | any; + getConversationLength(): number; + processActions( + message: Memory, + responses: Memory[], + state?: State, + callback?: HandlerCallback + ): Promise; + evaluate( + message: Memory, + state?: State, + didRespond?: boolean, + callback?: HandlerCallback, + responses?: Memory[] + ): Promise; + registerProvider(provider: Provider): void; + registerAction(action: Action): void; + registerEvaluator(evaluator: Evaluator): void; + ensureConnection({ + entityId, + roomId, + userName, + name, + source, + channelId, + serverId, + type, + worldId, + }: { + entityId: UUID; + roomId: UUID; + userName?: string; + name?: string; + source?: string; + channelId?: string; + serverId?: string; + type: ChannelType; + worldId?: UUID; + }): Promise; + ensureParticipantInRoom(entityId: UUID, roomId: UUID): Promise; + ensureWorldExists(world: World): Promise; + ensureRoomExists(room: Room): Promise; + composeState( + message: Memory, + filterList?: string[], + includeList?: string[] + ): Promise; + useModel( + modelType: T, + params: Omit | any + ): Promise; + registerModel( + modelType: ModelType | string, + handler: (params: any) => Promise + ): void; + getModel( + modelType: ModelType | string + ): ((runtime: IAgentRuntime, params: any) => Promise) | undefined; + registerEvent(event: string, handler: (params: any) => Promise): void; + getEvent(event: string): ((params: any) => Promise)[] | undefined; + emitEvent(event: string | string[], params: any): Promise; + registerTaskWorker(taskHandler: TaskWorker): void; + getTaskWorker(name: string): TaskWorker | undefined; + stop(): Promise; +} +⋮---- +registerPlugin(plugin: Plugin): Promise; +initialize(): Promise; +getKnowledge(message: Memory): Promise; +addKnowledge( + item: KnowledgeItem, + options: { + targetTokens: number; + overlap: number; + modelContextSize: number; + } + ): Promise; +⋮---- +getService(service: ServiceType | string): T | null; +getAllServices(): Map; +registerService(service: typeof Service): void; +registerDatabaseAdapter(adapter: IDatabaseAdapter): void; +setSetting( + key: string, + value: string | boolean | null | any, + secret: boolean + ): void; +getSetting(key: string): string | boolean | null | any; +getConversationLength(): number; +processActions( + message: Memory, + responses: Memory[], + state?: State, + callback?: HandlerCallback + ): Promise; +evaluate( + message: Memory, + state?: State, + didRespond?: boolean, + callback?: HandlerCallback, + responses?: Memory[] + ): Promise; +registerProvider(provider: Provider): void; +registerAction(action: Action): void; +registerEvaluator(evaluator: Evaluator): void; +ensureConnection({ + entityId, + roomId, + userName, + name, + source, + channelId, + serverId, + type, + worldId, + }: { + entityId: UUID; + roomId: UUID; + userName?: string; + name?: string; + source?: string; + channelId?: string; + serverId?: string; + type: ChannelType; + worldId?: UUID; + }): Promise; +ensureParticipantInRoom(entityId: UUID, roomId: UUID): Promise; +ensureWorldExists(world: World): Promise; +ensureRoomExists(room: Room): Promise; +composeState( + message: Memory, + filterList?: string[], + includeList?: string[] + ): Promise; +useModel( + modelType: T, + params: Omit | any + ): Promise; +registerModel( + modelType: ModelType | string, + handler: (params: any) => Promise + ): void; +getModel( + modelType: ModelType | string +): ((runtime: IAgentRuntime, params: any) +registerEvent(event: string, handler: (params: any) +getEvent(event: string): ((params: any) +emitEvent(event: string | string[], params: any): Promise; +registerTaskWorker(taskHandler: TaskWorker): void; +getTaskWorker(name: string): TaskWorker | undefined; +stop(): Promise; +⋮---- +export type KnowledgeItem = { + id: UUID; + content: Content; +}; +export enum KnowledgeScope { + SHARED = "shared", + PRIVATE = "private", +} +export enum CacheKeyPrefix { + KNOWLEDGE = "knowledge", +} +export interface DirectoryItem { + directory: string; + shared?: boolean; +} +export interface ChunkRow { + id: string; +} +export type GenerateTextParams = { + runtime: IAgentRuntime; + prompt: string; + modelType: ModelType; + maxTokens?: number; + temperature?: number; + frequencyPenalty?: number; + presencePenalty?: number; + stopSequences?: string[]; +}; +export interface TokenizeTextParams { + prompt: string; + modelType: ModelType; +} +export interface DetokenizeTextParams { + tokens: number[]; + modelType: ModelType; +} +export interface IVideoService extends Service { + isVideoUrl(url: string): boolean; + fetchVideoInfo(url: string): Promise; + downloadVideo(videoInfo: Media): Promise; + processVideo(url: string, runtime: IAgentRuntime): Promise; +} +⋮---- +isVideoUrl(url: string): boolean; +fetchVideoInfo(url: string): Promise; +downloadVideo(videoInfo: Media): Promise; +processVideo(url: string, runtime: IAgentRuntime): Promise; +⋮---- +export interface IBrowserService extends Service { + getPageContent( + url: string, + runtime: IAgentRuntime + ): Promise<{ title: string; description: string; bodyContent: string }>; +} +⋮---- +getPageContent( + url: string, + runtime: IAgentRuntime +): Promise< +⋮---- +export interface IPdfService extends Service { + convertPdfToText(pdfBuffer: Buffer): Promise; +} +⋮---- +convertPdfToText(pdfBuffer: Buffer): Promise; +⋮---- +export interface IFileService extends Service { + uploadFile( + imagePath: string, + subDirectory: string, + useSignedUrl: boolean, + expiresIn: number + ): Promise<{ + success: boolean; + url?: string; + error?: string; + }>; + generateSignedUrl(fileName: string, expiresIn: number): Promise; +} +⋮---- +uploadFile( + imagePath: string, + subDirectory: string, + useSignedUrl: boolean, + expiresIn: number +): Promise< +generateSignedUrl(fileName: string, expiresIn: number): Promise; +⋮---- +export interface ITeeLogService extends Service { + log( + agentId: string, + roomId: string, + entityId: string, + type: string, + content: string + ): Promise; + generateAttestation( + reportData: string, + hashAlgorithm?: T | any + ): Promise; + getAllAgents(): Promise; + getAgent(agentId: string): Promise; + getLogs( + query: TeeLogQuery, + page: number, + pageSize: number + ): Promise>; +} +⋮---- +log( + agentId: string, + roomId: string, + entityId: string, + type: string, + content: string + ): Promise; +generateAttestation( + reportData: string, + hashAlgorithm?: T | any + ): Promise; +getAllAgents(): Promise; +getAgent(agentId: string): Promise; +getLogs( + query: TeeLogQuery, + page: number, + pageSize: number + ): Promise>; +⋮---- +export interface TestCase { + name: string; + fn: (runtime: IAgentRuntime) => Promise | void; +} +export interface TestSuite { + name: string; + tests: TestCase[]; +} +export interface TeeLog { + id: string; + agentId: string; + roomId: string; + entityId: string; + type: string; + content: string; + timestamp: number; + signature: string; +} +export interface TeeLogQuery { + agentId?: string; + roomId?: string; + entityId?: string; + type?: string; + containsContent?: string; + startTimestamp?: number; + endTimestamp?: number; +} +export interface TeeAgent { + id: string; + agentId: string; + agentName: string; + createdAt: number; + publicKey: string; + attestation: string; +} +export interface TeePageQuery { + page: number; + pageSize: number; + total?: number; + data?: Result; +} +export abstract class TeeLogDAO +⋮---- +abstract initialize(): Promise; +abstract addLog(log: TeeLog): Promise; +abstract getPagedLogs( + query: TeeLogQuery, + page: number, + pageSize: number + ): Promise>; +abstract addAgent(agent: TeeAgent): Promise; +abstract getAgent(agentId: string): Promise; +abstract getAllAgents(): Promise; +⋮---- +export enum TEEMode { + OFF = "OFF", + LOCAL = "LOCAL", + DOCKER = "DOCKER", + PRODUCTION = "PRODUCTION", +} +export interface RemoteAttestationQuote { + quote: string; + timestamp: number; +} +export interface DeriveKeyAttestationData { + agentId: string; + publicKey: string; + subject?: string; +} +export interface RemoteAttestationMessage { + agentId: string; + timestamp: number; + message: { + entityId: string; + roomId: string; + content: string; + }; +} +export interface SgxAttestation { + quote: string; + timestamp: number; +} +export enum TeeType { + SGX_GRAMINE = "sgx_gramine", + TDX_DSTACK = "tdx_dstack", +} +export interface TeeVendorConfig { + [key: string]: unknown; +} +export interface TeePluginConfig { + vendor?: string; + vendorConfig?: TeeVendorConfig; +} +export interface TaskWorker { + name: string; + execute: ( + runtime: IAgentRuntime, + options: { [key: string]: unknown }, + task: Task + ) => Promise; + validate?: ( + runtime: IAgentRuntime, + message: Memory, + state: State + ) => Promise; +} +export interface Task { + id?: UUID; + name: string; + updatedAt?: number; + metadata?: { + updateInterval?: number; + options?: { + name: string; + description: string; + }[]; + [key: string]: unknown; + }; + description: string; + roomId?: UUID; + worldId?: UUID; + tags: string[]; +} +export enum Role { + OWNER = "OWNER", + ADMIN = "ADMIN", + NONE = "NONE", +} +export interface Setting { + name: string; + description: string; + usageDescription: string; + value: string | boolean | null; + required: boolean; + public?: boolean; + secret?: boolean; + validation?: (value: any) => boolean; + dependsOn?: string[]; + onSetAction?: (value: any) => string; + visibleIf?: (settings: { [key: string]: Setting }) => boolean; +} +export interface WorldSettings { + [key: string]: Setting; +} +export interface OnboardingConfig { + settings: { + [key: string]: Omit; + }; +} +export interface BaseModelParams { + runtime: IAgentRuntime; +} +export interface TextGenerationParams extends BaseModelParams { + prompt: string; + temperature?: number; + maxTokens?: number; + stopSequences?: string[]; + frequencyPenalty?: number; + presencePenalty?: number; +} +export interface TextEmbeddingParams extends BaseModelParams { + text: string; +} +export interface TokenizeTextParams extends BaseModelParams { + prompt: string; + modelType: ModelType; +} +export interface DetokenizeTextParams extends BaseModelParams { + tokens: number[]; + modelType: ModelType; +} +export interface ImageGenerationParams extends BaseModelParams { + prompt: string; + size?: string; + count?: number; +} +export interface ImageDescriptionParams extends BaseModelParams { + imageUrl: string; + prompt?: string; +} +export interface TranscriptionParams extends BaseModelParams { + audioUrl: string; + prompt?: string; +} +export interface TextToSpeechParams extends BaseModelParams { + text: string; + voice?: string; + speed?: number; +} +export interface AudioProcessingParams extends BaseModelParams { + audioUrl: string; + processingType: string; +} +export interface VideoProcessingParams extends BaseModelParams { + videoUrl: string; + processingType: string; +} +export type JSONSchema = { + type: string; + properties?: Record; + required?: string[]; + items?: JSONSchema; + [key: string]: any; +}; +export interface ObjectGenerationParams extends BaseModelParams { + prompt: string; + schema?: JSONSchema; + output?: "object" | "array" | "enum"; + enumValues?: string[]; + modelType?: ModelType; + temperature?: number; + stopSequences?: string[]; +} +export interface ModelParamsMap { + [ModelTypes.TEXT_SMALL]: TextGenerationParams; + [ModelTypes.TEXT_LARGE]: TextGenerationParams; + [ModelTypes.TEXT_EMBEDDING]: TextEmbeddingParams | string | null; + [ModelTypes.TEXT_TOKENIZER_ENCODE]: TokenizeTextParams; + [ModelTypes.TEXT_TOKENIZER_DECODE]: DetokenizeTextParams; + [ModelTypes.TEXT_REASONING_SMALL]: TextGenerationParams; + [ModelTypes.TEXT_REASONING_LARGE]: TextGenerationParams; + [ModelTypes.IMAGE]: ImageGenerationParams; + [ModelTypes.IMAGE_DESCRIPTION]: ImageDescriptionParams | string; + [ModelTypes.TRANSCRIPTION]: TranscriptionParams | Buffer | string; + [ModelTypes.TEXT_TO_SPEECH]: TextToSpeechParams | string; + [ModelTypes.AUDIO]: AudioProcessingParams; + [ModelTypes.VIDEO]: VideoProcessingParams; + [ModelTypes.OBJECT_SMALL]: ObjectGenerationParams; + [ModelTypes.OBJECT_LARGE]: ObjectGenerationParams; + [key: string]: BaseModelParams | any; +} +export interface ModelResultMap { + [ModelTypes.TEXT_SMALL]: string; + [ModelTypes.TEXT_LARGE]: string; + [ModelTypes.TEXT_EMBEDDING]: number[]; + [ModelTypes.TEXT_TOKENIZER_ENCODE]: number[]; + [ModelTypes.TEXT_TOKENIZER_DECODE]: string; + [ModelTypes.TEXT_REASONING_SMALL]: string; + [ModelTypes.TEXT_REASONING_LARGE]: string; + [ModelTypes.IMAGE]: { url: string }[]; + [ModelTypes.IMAGE_DESCRIPTION]: { title: string; description: string }; + [ModelTypes.TRANSCRIPTION]: string; + [ModelTypes.TEXT_TO_SPEECH]: Readable | Buffer; + [ModelTypes.AUDIO]: any; + [ModelTypes.VIDEO]: any; + [ModelTypes.OBJECT_SMALL]: any; + [ModelTypes.OBJECT_LARGE]: any; + [key: string]: any; +} +export enum EventType { + WORLD_JOINED = "WORLD_JOINED", + WORLD_CONNECTED = "WORLD_CONNECTED", + WORLD_LEFT = "WORLD_LEFT", + ENTITY_JOINED = "ENTITY_JOINED", + ENTITY_LEFT = "ENTITY_LEFT", + ENTITY_UPDATED = "ENTITY_UPDATED", + ROOM_JOINED = "ROOM_JOINED", + ROOM_LEFT = "ROOM_LEFT", + MESSAGE_RECEIVED = "MESSAGE_RECEIVED", + MESSAGE_SENT = "MESSAGE_SENT", + VOICE_MESSAGE_RECEIVED = "VOICE_MESSAGE_RECEIVED", + VOICE_MESSAGE_SENT = "VOICE_MESSAGE_SENT", + REACTION_RECEIVED = "REACTION_RECEIVED", + POST_GENERATED = "POST_GENERATED", + INTERACTION_RECEIVED = "INTERACTION_RECEIVED", + RUN_STARTED = "RUN_STARTED", + RUN_ENDED = "RUN_ENDED", + RUN_TIMEOUT = "RUN_TIMEOUT", + ACTION_STARTED = "ACTION_STARTED", + ACTION_COMPLETED = "ACTION_COMPLETED", + EVALUATOR_STARTED = "EVALUATOR_STARTED", + EVALUATOR_COMPLETED = "EVALUATOR_COMPLETED", +} +export enum PlatformPrefix { + DISCORD = "DISCORD", + TELEGRAM = "TELEGRAM", + TWITTER = "TWITTER", +} +export interface EventPayload { + runtime: IAgentRuntime; + source: string; +} +export interface WorldPayload extends EventPayload { + world: World; + rooms: Room[]; + entities: Entity[]; +} +export interface EntityPayload extends EventPayload { + entityId: UUID; + worldId?: UUID; + roomId?: UUID; + metadata?: { + orginalId: string; + username: string; + displayName?: string; + [key: string]: any; + }; +} +export interface MessagePayload extends EventPayload { + message: Memory; + callback?: HandlerCallback; +} +export interface RunEventPayload extends EventPayload { + runId: UUID; + messageId: UUID; + roomId: UUID; + entityId: UUID; + startTime: number; + status: "started" | "completed" | "timeout"; + endTime?: number; + duration?: number; + error?: string; +} +export interface ActionEventPayload extends EventPayload { + actionId: UUID; + actionName: string; + startTime?: number; + completed?: boolean; + error?: Error; +} +export interface EvaluatorEventPayload extends EventPayload { + evaluatorId: UUID; + evaluatorName: string; + startTime?: number; + completed?: boolean; + error?: Error; +} +export interface EventPayloadMap { + [EventType.WORLD_JOINED]: WorldPayload; + [EventType.WORLD_CONNECTED]: WorldPayload; + [EventType.WORLD_LEFT]: WorldPayload; + [EventType.ENTITY_JOINED]: EntityPayload; + [EventType.ENTITY_LEFT]: EntityPayload; + [EventType.ENTITY_UPDATED]: EntityPayload; + [EventType.MESSAGE_RECEIVED]: MessagePayload; + [EventType.MESSAGE_SENT]: MessagePayload; + [EventType.REACTION_RECEIVED]: MessagePayload; + [EventType.POST_GENERATED]: MessagePayload; + [EventType.INTERACTION_RECEIVED]: MessagePayload; + [EventType.RUN_STARTED]: RunEventPayload; + [EventType.RUN_ENDED]: RunEventPayload; + [EventType.RUN_TIMEOUT]: RunEventPayload; + [EventType.ACTION_STARTED]: ActionEventPayload; + [EventType.ACTION_COMPLETED]: ActionEventPayload; + [EventType.EVALUATOR_STARTED]: EvaluatorEventPayload; + [EventType.EVALUATOR_COMPLETED]: EvaluatorEventPayload; +} +export type EventHandler = ( + payload: EventPayloadMap[T] +) => Promise; +export enum SOCKET_MESSAGE_TYPE { + ROOM_JOINING = 1, + SEND_MESSAGE = 2, +} +export interface MessageMemory extends Memory { + metadata: MessageMetadata; + content: Content & { + text: string; + }; +} +export function createMessageMemory(params: { + id?: UUID; + entityId: UUID; + agentId?: UUID; + roomId: UUID; + content: Content & { text: string }; + embedding?: number[]; +}): MessageMemory +export interface TypedService + extends Service { + config: ConfigType; + process(input: unknown): Promise; +} +⋮---- +process(input: unknown): Promise; +⋮---- +export function getTypedService>( + runtime: IAgentRuntime, + serviceType: ServiceType +): T | null +export type Result = Success | Failure; +export class Success +⋮---- +constructor(value: T) +map(fn: (value: T) => U): Success +unwrapOr(_defaultValue: T): T +⋮---- +export class Failure +⋮---- +constructor(error: E) +mapError(fn: (error: E) => F): Failure +unwrapOr(defaultValue: T): T +⋮---- +export function success(value: T): Success +export function failure(error: E): Failure +export function isDocumentMetadata( + metadata: MemoryMetadata +): metadata is DocumentMetadata +export function isFragmentMetadata( + metadata: MemoryMetadata +): metadata is FragmentMetadata +export function isMessageMetadata( + metadata: MemoryMetadata +): metadata is MessageMetadata +export function isDescriptionMetadata( + metadata: MemoryMetadata +): metadata is DescriptionMetadata +export function isCustomMetadata( + metadata: MemoryMetadata +): metadata is CustomMetadata +export interface ServiceError { + code: string; + message: string; + details?: unknown; + cause?: Error; +} +export function getVideoService(runtime: IAgentRuntime): IVideoService | null +export function getBrowserService( + runtime: IAgentRuntime +): IBrowserService | null +export function getPdfService(runtime: IAgentRuntime): IPdfService | null +export function getFileService(runtime: IAgentRuntime): IFileService | null +export function isDocumentMemory( + memory: Memory +): memory is Memory & +export function isFragmentMemory( + memory: Memory +): memory is Memory & +export function getMemoryText(memory: Memory, defaultValue = ""): string +/** + * Safely create a ServiceError from any caught error + */ +export function createServiceError( + error: unknown, + code = "UNKNOWN_ERROR" +): ServiceError +export type StateValue = + | string + | number + | boolean + | null + | StateObject + | StateArray; +export interface StateObject { + [key: string]: StateValue; +} +export type StateArray = StateValue[]; +export interface EnhancedState { + values: StateObject; + data: StateObject; + text: string; + [key: string]: StateValue; +} +export type ComponentData = Record; +export type EventDataObject = Record; +export type TypedEventHandler = (data: EventDataObject) => Promise | void; +export type DbConnection = unknown; +export type MetadataObject = Record; +export type ModelHandler = ( + runtime: IAgentRuntime, + params: Record +) => Promise; +export type ServiceConfig = Record; +export type MessageMemoryManager = IMemoryManager; +export type DocumentMemoryManager = IMemoryManager< + Memory & { metadata: DocumentMetadata } +>; +export type FragmentMemoryManager = IMemoryManager< + Memory & { metadata: FragmentMetadata } +>; +```` + +## File: packages/docs/docs/core/actions.md +````markdown +--- +sidebar_position: 6 +--- + +# ⚡ Actions + +Actions define how agents respond to and interact with messages. They enable agents to perform tasks beyond simple message responses by integrating with external systems and modifying behavior. + +## Overview + +1. Structure: + +An Action consists of: + +- `name`: Unique identifier +- `similes`: Alternative names/triggers +- `description`: Purpose and usage explanation +- `validate`: Function to check if action is appropriate +- `handler`: Core implementation logic +- `examples`: Sample usage patterns +- `suppressInitialMessage`: Optional flag to suppress initial response + + +2. Validation: + +- Checks if the action can be executed +- Consider conversation state +- Validate required + +--- + +## Implementation + +```typescript +interface Action { + name: string; + similes: string[]; + description: string; + examples: ActionExample[][]; + handler: Handler; + validate: Validator; + suppressInitialMessage?: boolean; +} +``` + +Source: https://github.com/elizaOS/eliza/blob/main/packages/core/src/types.ts + + +### Basic Action Template + +```typescript +const customAction: Action = { + name: "CUSTOM_ACTION", + similes: ["ALTERNATE_NAME", "OTHER_TRIGGER"], + description: "Detailed description of when and how to use this action", + validate: async (runtime: IAgentRuntime, message: Memory) => { + // Validation logic + return true; + }, + handler: async (runtime: IAgentRuntime, message: Memory) => { + // Implementation logic + return true; + }, + examples: [ + [ + { + user: "{{user1}}", + content: { text: "Trigger message" }, + }, + { + user: "{{user2}}", + content: { text: "Response", action: "CUSTOM_ACTION" }, + }, + ], + ], +}; +``` + +#### Character File Example + +Actions can be used in character files as well. Here's an example from: https://github.com/elizaOS/characters/blob/main/sbf.character.json + +```json + "messageExamples": [ + [ + { + "user": "{{user1}}", + "content": { + "text": "Can you help transfer some SOL?" + } + }, + { + "user": "SBF", + "content": { + "text": "yeah yeah for sure, sending SOL is pretty straightforward. just need the recipient and amount. everything else is basically fine, trust me.", + "action": "SEND_SOL" + } + } + ], +``` + +--- + +## Example Implementations + +Actions can be found across various plugins in the Eliza ecosystem, with a comprehensive collection available at https://github.com/elizaos-plugins. Here are some notable examples: + +### Blockchain and Token Actions +- Transfers: `SEND_TOKEN`, `SEND_SOL`, `SEND_NEAR`, `SEND_AVAIL`, `SEND_TON`, `SEND_TOKENS`, `COSMOS_TRANSFER`, `CROSS_CHAIN_TRANSFER` +- Token Management: `CREATE_TOKEN`, `GET_TOKEN_INFO`, `GET_BALANCE`, `GET_TOKEN_PRICE`, `TOKEN_SWAP`, `SWAP_TOKEN`, `EXECUTE_SPOT_TRADE` +- Blockchain Interactions: `READ_CONTRACT`, `WRITE_CONTRACT`, `DEPLOY_CONTRACT`, `DEPLOY_TOKEN`, `GET_TRANSACTION`, `GET_CURRENT_NONCE`, `GET_CONTRACT_SCHEMA` + +### Cryptographic and Security Actions +- Signature and Authentication: `ECDSA_SIGN`, `LIT_ACTION`, `REMOTE_ATTESTATION`, `AUTHENTICATE` +- Wallet and Key Management: `ERC20_TRANSFER`, `WALLET_TRANSFER`, `BRIDGE_OPERATIONS` + +### Staking and Governance +- Staking Actions: `STAKE`, `DELEGATE_TOKEN`, `UNDELEGATE_TOKEN`, `GET_STAKE_BALANCE`, `TOKENS_REDELEGATE` +- Governance Actions: `VOTE_ON_PROPOSAL`, `PROPOSE`, `EXECUTE_PROPOSAL`, `QUEUE_PROPOSAL` + +### AI and Agent Management +- Agent Creation: `LAUNCH_AGENT`, `START_SESSION`, `CREATE_AND_REGISTER_AGENT` +- AI-Specific Actions: `GENERATE_IMAGE`, `DESCRIBE_IMAGE`, `GENERATE_VIDEO`, `GENERATE_MUSIC`, `GET_INFERENCE`, `GENERATE_MEME` + +### Media and Content Generation +- Image and Multimedia: `SEND_GIF`, `GENERATE_3D`, `GENERATE_COLLECTION`, `MINT_NFT`, `LIST_NFT`, `SWEEP_FLOOR_NFT` +- Audio and Voice: `EXTEND_AUDIO`, `CREATE_TTS` + +### Decentralized Infrastructure (DePIN) +- Project Interactions: `DEPIN_TOKENS`, `DEPIN_ON_CHAIN`, `ANALYZE_DEPIN_PROJECTS` + +### Search and Information Retrieval +- Data Search: `WEB_SEARCH`, `GET_TOKEN_PRICE_BY_ADDRESS`, `GET_TRENDING_POOLS`, `GET_NEW_COINS`, `GET_MARKETS` + +### Blockchain and Trading +- Specialized Actions: `GET_QUOTE_0X`, `EXECUTE_SWAP_0X`, `CANCEL_ORDERS`, `GET_INDICATIVE_PRICE` + +### Social and Communication +- Platform Interactions: `TWEET`, `POST_TWEET`, `QUOTE`, `JOIN_VOICE`, `LEAVE_VOICE`, `TRANSCRIBE_MEDIA`, `SUMMARIZE_CONVERSATION` + +### Utility Actions +- General Utilities: `FAUCET`, `SUBMIT_DATA`, `PRICE_CHECK`, `WEATHER`, `NEWS` + +Check out the [ElizaOS Plugins org](https://github.com/elizaos-plugins) on GitHub if interested in studying or using any of these. + +### Image Generation Action + +Here's a comprehensive example of an image generation action: + +```typescript +import { Action, IAgentRuntime, Memory, State } from "@elizaos/core"; + +// Example image generation action +const generateImageAction: Action = { + name: "GENERATE_IMAGE", + similes: ["CREATE_IMAGE", "MAKE_IMAGE", "DRAW"], + description: "Generates an image based on the user's description", + suppressInitialMessage: true, // Suppress initial response since we'll generate our own + + // Validate if this action should be used + validate: async (runtime: IAgentRuntime, message: Memory) => { + const text = message.content.text.toLowerCase(); + // Check if message contains image generation triggers + return ( + text.includes("generate") || + text.includes("create") || + text.includes("draw") || + text.includes("make an image") + ); + }, + + // Handle the action execution + handler: async (runtime: IAgentRuntime, message: Memory, state?: State) => { + try { + // Get image service + const imageService = runtime.getService(ServiceType.IMAGE_GENERATION); + + // Generate image + const imageUrl = await imageService.generateImage(message.content.text); + + // Create response with generated image + await runtime.messageManager.createMemory({ + id: generateId(), + content: { + text: "Here's the image I generated:", + attachments: [{ + type: "image", + url: imageUrl + }] + }, + userId: runtime.agentId, + roomId: message.roomId, + }); + + return true; + } catch (error) { + console.error("Image generation failed:", error); + return false; + } + }, + + // Example usage patterns + examples: [ + [ + { + user: "{{user1}}", + content: { + text: "Can you generate an image of a sunset?" + } + }, + { + user: "{{user2}}", + content: { + text: "I'll create that image for you", + action: "GENERATE_IMAGE" + } + } + ] + ] +}; +``` + +### Basic Conversation Actions + +You can find these samples in the plugin-bootstrap package: https://github.com/elizaOS/eliza/tree/main/packages/plugin-bootstrap/src/actions + +#### CONTINUE + +For continuing conversations: + +```typescript +const continueAction: Action = { + name: "CONTINUE", + similes: ["ELABORATE", "GO_ON"], + description: "Continues the conversation when appropriate", + + validate: async (runtime: IAgentRuntime, message: Memory) => { + // Check if message warrants continuation + const text = message.content.text.toLowerCase(); + return ( + text.includes("tell me more") || + text.includes("what else") || + text.includes("continue") || + text.endsWith("?") + ); + }, + + handler: async (runtime: IAgentRuntime, message: Memory, state?: State) => { + // Get recent conversation context + const recentMessages = await runtime.messageManager.getMemories({ + roomId: message.roomId, + count: 5 + }); + + // Generate contextual response + const response = await runtime.generateResponse( + message, + recentMessages, + state + ); + + // Store response + await runtime.messageManager.createMemory({ + id: generateId(), + content: response, + userId: runtime.agentId, + roomId: message.roomId + }); + + return true; + }, + + examples: [ + [ + { + user: "{{user1}}", + content: { text: "Tell me more about that" } + }, + { + user: "{{user2}}", + content: { + text: "I'll continue explaining...", + action: "CONTINUE" + } + } + ] + ] +}; +``` + +#### IGNORE + +For ending conversations: + +```typescript +const ignoreAction: Action = { + name: "IGNORE", + similes: ["STOP_TALKING", "END_CONVERSATION"], + description: "Stops responding when conversation is complete or irrelevant", + + validate: async (runtime: IAgentRuntime, message: Memory) => { + const text = message.content.text.toLowerCase(); + return ( + text.includes("goodbye") || + text.includes("bye") || + text.includes("thanks") || + text.length < 2 + ); + }, + + handler: async (runtime: IAgentRuntime, message: Memory) => { + // No response needed + return true; + }, + + examples: [ + [ + { + user: "{{user1}}", + content: { text: "Thanks, goodbye!" } + }, + { + user: "{{user2}}", + content: { + text: "", + action: "IGNORE" + } + } + ] + ] +}; +``` + +--- + +## FAQ + +### What are Actions in Eliza? +Actions are core building blocks that define how agents interact with messages and perform tasks beyond simple text responses. + +### How do Actions work? +Actions consist of a name, description, validation function, and handler function that determine when and how an agent can perform a specific task. + +### What can Actions do? +Actions enable agents to interact with external systems, modify behavior, process complex workflows, and extend capabilities beyond conversational responses. + +### What are some example Actions? +Common actions include CONTINUE (extend dialogue), IGNORE (end conversation), GENERATE_IMAGE (create images), TRANSFER (move tokens), and READ_CONTRACT (retrieve blockchain data). + +### How do I create a custom Action? +Define an action with a unique name, validation function to check eligibility, handler function to implement the logic, and provide usage examples. + +### What makes a good Action? +A good action has a clear, single purpose, robust input validation, comprehensive error handling, and provides meaningful interactions. + +### Can Actions be chained together? +Yes, actions can be composed and chained to create complex workflows and multi-step interactions. + +### How are Actions different from tools? +Actions are more comprehensive, ensuring the entire process happens, while tools are typically more focused on specific, discrete operations. + +### Where are Actions defined? +Actions can be defined in character files, plugins, or directly in agent configurations. + +## Further Reading + +- [characterfile](./characterfile.md) +- [providers](./providers.md) +```` + +## File: packages/docs/docs/core/agents.md +````markdown +# 🤖 Agent Runtime + +The `AgentRuntime` is the core runtime environment for Eliza agents. It handles message processing, state management, plugin integration, and interaction with external services. You can think of it as the brains that provide the high-level orchestration layer for Eliza agents. + +![](/img/eliza-architecture.jpg) + +The runtime follows this general flow: +1. Agent loads character config, plugins, and services + - Processes knowledge sources (e.g., documents, directories) +2. Receives a message, composes the state +3. Processes actions and then evaluates + - Retrieves relevant knowledge fragments using RAG +4. Generates and executes responses, then evaluates +5. Updates memory and state + + +--- + +## Overview + +The [AgentRuntime](/api/classes/AgentRuntime) class is the primary implementation of the [IAgentRuntime](/api/interfaces/IAgentRuntime) interface, which manages the agent's core functions, including: + + +| Component | Description | API Reference | Related Files | +|---------|-------------|---------------|---------------| +| **Clients** | Supports multiple communication platforms for seamless interaction. | [Clients API](/api/interfaces/IAgentRuntime/#clients) | [`clients.ts`](https://github.com/elizaos-plugins/client-discord/blob/main/__tests__/discord-client.test.ts), [`Discord`](https://github.com/elizaos-plugins/client-discord), [`Telegram`](https://github.com/elizaos-plugins/client-telegram), [`Twitter`](https://github.com/elizaos-plugins/client-twitter), [`Farcaster`](https://github.com/elizaos-plugins/client-farcaster), [`Lens`](https://github.com/elizaos-plugins/client-lens), [`Slack`](https://github.com/elizaos-plugins/client-slack), [`Auto`](https://github.com/elizaos-plugins/client-auto), [`GitHub`](https://github.com/elizaos-plugins/client-github) | +| **State** | Maintains context for coherent cross-platform interactions, updates dynamically. Also tracks goals, knowledge, and recent interactions | [State API](/api/interfaces/State) | [`state.ts`](https://github.com/elizaos/runtime/state.ts) | +| **Plugins** | Dynamic extensions of agent functionalities using custom actions, evaluators, providers, and adapters | [Plugins API](/api/type-aliases/Plugin/) | [`plugins.ts`](https://github.com/elizaos/runtime/plugins.ts), [actions](../actions), [evaluators](../evaluators), [providers](../providers) | +| **Services** | Connects with external services for `IMAGE_DESCRIPTION`, `TRANSCRIPTION`, `TEXT_GENERATION`, `SPEECH_GENERATION`, `VIDEO`, `PDF`, `BROWSER`, `WEB_SEARCH`, `EMAIL_AUTOMATION`, and more | [Services API](/api/interfaces/IAgentRuntime/#services) | [`services.ts`](https://github.com/elizaos/runtime/services.ts) | +| **Memory Systems** | Creates, retrieves, and embeds memories and manages conversation history. | [Memory API](/api/interfaces/IMemoryManager) | [`memory.ts`](https://github.com/elizaos/runtime/memory.ts) | +| **Database Adapters** | Persistent storage and retrieval for memories and knowledge | [databaseAdapter](api/interfaces/IAgentRuntime/#databaseAdapter) | [`MongoDB`](https://github.com/elizaos-plugins/adapter-mongodb), [`PostgreSQL`](https://github.com/elizaos-plugins/adapter-postgres), [`SQLite`](https://github.com/elizaos-plugins/adapter-sqlite), [`Supabase`](https://github.com/elizaos-plugins/adapter-supabase), [`PGLite`](https://github.com/elizaos-plugins/adapter-pglite), [`Qdrant`](https://github.com/elizaos-plugins/adapter-qdrant), [`SQL.js`](https://github.com/elizaos-plugins/adapter-sqljs) | +| **Cache Management** | Provides flexible storage and retrieval via various caching methods. | [Cache API](/api/interfaces/ICacheManager) | [`cache.ts`](https://github.com/elizaos/runtime/cache.ts) | + + + +
+Advanced: IAgentRuntime Interface +```typescript +interface IAgentRuntime { + // Core identification + agentId: UUID; + token: string; + serverUrl: string; + + // Configuration + character: Character; // Personality and behavior settings + modelProvider: ModelProviderName; // AI model to use + imageModelProvider: ModelProviderName; + imageVisionModelProvider: ModelProviderName; + + // Components + plugins: Plugin[]; // Additional capabilities + clients: Record; // Platform connections + providers: Provider[]; // Real-time data sources + actions: Action[]; // Available behaviors + evaluators: Evaluator[]; // Analysis & learning + + // Memory Management + messageManager: IMemoryManager; // Conversation history + descriptionManager: IMemoryManager; + documentsManager: IMemoryManager; // Large documents + knowledgeManager: IMemoryManager; // Search & retrieval + ragKnowledgeManager: IRAGKnowledgeManager; // RAG integration + loreManager: IMemoryManager; // Character background + + // Storage & Caching + databaseAdapter: IDatabaseAdapter; // Data persistence + cacheManager: ICacheManager; // Performance optimization + + // Services + services: Map; // External integrations + + // Networking + fetch: (url: string, options: any) => Promise; +} +``` +Source: [/api/interfaces/IAgentRuntime/](/api/interfaces/IAgentRuntime/) + +
+ + +--- + +### **Key Methods** +- **`initialize()`**: Sets up the agent's runtime environment, including services, plugins, and knowledge processing. +- **`processActions()`**: Executes actions based on message content and state. +- **`evaluate()`**: Assesses messages and state using registered evaluators. +- **`composeState()`**: Constructs the agent's state object for response generation. +- **`updateRecentMessageState()`**: Updates the state with recent messages and attachments. +- **`registerService()`**: Adds a service to the runtime. +- **`registerMemoryManager()`**: Registers a memory manager for specific types of memories. +- **`ensureRoomExists()` / `ensureUserExists()`**: Ensures the existence of rooms and users in the database. + +WIP + + +--- + +## Service System + +Services provide specialized functionality with standardized interfaces that can be accessed cross-platform: + +
+See Example + +```typescript +// Speech Generation +const speechService = runtime.getService( + ServiceType.SPEECH_GENERATION +); +const audioStream = await speechService.generate(runtime, text); + +// PDF Processing +const pdfService = runtime.getService(ServiceType.PDF); +const textContent = await pdfService.convertPdfToText(pdfBuffer); +``` +
+ + +--- + +## State Management + +The runtime maintains comprehensive state through the State interface: + +```typescript +interface State { + // Core identifiers + userId?: UUID; + agentId?: UUID; + roomId: UUID; + + // Character information + bio: string; + lore: string; + messageDirections: string; + postDirections: string; + + // Conversation context + actors: string; + actorsData?: Actor[]; + recentMessages: string; + recentMessagesData: Memory[]; + + // Goals and knowledge + goals?: string; + goalsData?: Goal[]; + knowledge?: string; + knowledgeData?: KnowledgeItem[]; + ragKnowledgeData?: RAGKnowledgeItem[]; +} + +// State management methods +async function manageState() { + // Initial state composition + const state = await runtime.composeState(message, { + additionalContext: "custom context" + }); + + // Update state with new messages + const updatedState = await runtime.updateRecentMessageState(state); +} +``` + +--- + +## Plugin System + +Plugins extend agent functionality through a modular interface. The runtime supports various types of plugins including clients, services, adapters, and more: + +```typescript +interface Plugin { + name: string; + description: string; + actions?: Action[]; // Custom behaviors + providers?: Provider[]; // Data providers + evaluators?: Evaluator[]; // Response assessment + services?: Service[]; // Background processes + clients?: Client[]; // Platform integrations + adapters?: Adapter[]; // Database/cache adapters +} +``` + +Plugins can be configured through [characterfile](./characterfile) settings: + +```json +{ + "name": "MyAgent", + "plugins": [ + "@elizaos/plugin-solana", + "@elizaos/plugin-twitter" + ] +} +``` + +For detailed information about plugin development and usage, see the [ElizaOS Registry](https://github.com/elizaos-plugins). + +--- + +## Running Multiple Agents + +To run multiple agents: + +```bash +bun start:client +``` + +Then read the [Documentation](https://elizaos.github.io/eliza/) to learn how to customize your Eliza. + +--- + +### Automatically Start Eliza + +For a more automated setup: + +```bash +git clone git@github.com:elizaOS/eliza.git +cd eliza + +# Run the start script with verbose logging +./scripts/start.sh -v +``` + +The start script handles all dependencies, environment setup, and character management automatically. + +--- + +### Modify Character + +1. Open `packages/core/src/defaultCharacter.ts` to modify the default character. Uncomment and edit. + +```bash +git clone git@github.com:elizaOS/eliza.git +cd eliza +``` + +:::tip +If you're planning on doing development, we suggest using the code on the develop branch: +```bash +git checkout develop +``` + +From the main repo you can also download [sample character files](https://github.com/elizaos/characters) this way: +```bash +git submodule update --init +``` +::: + +Install the dependencies + +```bash +pnpm install +``` + +> **Note:** you may need to use --no-frozen-lockfile if it gives a message about the frozen lock file being out of date. + +Compile the typescript: + +```bash +pnpm build +``` + +--- + +## Start the Agent + +[Character files](./core/characterfile.md) are where you can configure your agent's personality, lore, and capabilities via plugins. Inform eliza which character you want to run: + +```bash +pnpm start --character="characters/deep-thought.character.json" +``` + +You can load multiple characters with a comma-separated list: + +```bash +pnpm start --characters="characters/deep-thought.character.json,characters/sbf.character.json" +``` + +By default the agent will be accessible via the terminal and REST API. + +#### Chat Client + +If you're using the main [eliza repo](https://github.com/elizaos/eliza) and want to use the chat client, open a new terminal window and run the client's http server: + +```bash +pnpm start:client +``` + +Once the client is running, you'll see a message like this: + +``` +➜ Local: http://localhost:5173/ +``` + +Simply click the link or open your browser to `http://localhost:5173/`. You'll see the chat interface connect to the system, and you can begin interacting with your character. + +--- + +## Additional Configuration + +You can load plugins or additional client support with your character file to unlock more capabilities for your agent. + +### Add Plugins and Clients + +Here's how to import and register plugins in your character file: + +```typescript +{ + "name": "Eliza", + "clients": ["telegram"], + // ... other config options + "plugins": ["@elizaos/plugin-image"], +} +``` + +There are two ways to get a list of available plugins: + +1. Web Interface + +Go https://elizaos.github.io/registry/ or the [Showcase](/showcase) and search for plugins + +2. CLI Interface + +```bash +$ npx elizaos plugins list +``` + +Here's a sample list of plugins you can check out! + +| plugin name | Description | +| ----------- | ----------- | +| [`@elizaos/plugin-llama`](https://github.com/elizaos-plugins/plugin-llama) | Run LLM models on your local machine +| [`@elizaos/client-twitter`](https://github.com/elizaos-plugins/client-twitter) | Twitter bot integration +| [`@elizaos/client-discord`](https://github.com/elizaos-plugins/client-discord) | Discord bot integration +| [`@elizaos/client-telegram`](https://github.com/elizaos-plugins/client-telegram) | Telegram integration +| [`@elizaos/plugin-image`](https://github.com/elizaos-plugins/plugin-image) | Image processing and analysis +| [`@elizaos/plugin-video`](https://github.com/elizaos-plugins/plugin-video) | Video processing capabilities +| [`@elizaos/plugin-browser`](https://github.com/elizaos-plugins/plugin-browser) | Web scraping capabilities +| [`@elizaos/plugin-pdf`](https://github.com/elizaos-plugins/plugin-pdf) | PDF processing + + + +### Configure Environment + +There are two ways to configure elizaOS + +### Option 1: Default .env file + +Copying the `.example.env` file and editing is the simpler option especially if you plan to just host one agent: + +```bash +cp .env.example .env +nano .env +``` + +### Option 2: Secrets in the character file + +This option allows you finer grain control over which character uses what resources and is required if you want multiple agents but using different keys. For example: + + +```typescript +{ + "name": "eliza", + // ... other config options + "settings": { + "secrets": { + "DISCORD_APPLICATION_ID": "1234", + "DISCORD_API_TOKEN": "xxxx", + "OPENAI_API_KEY": "sk-proj-xxxxxxxxx-..." + } + } +``` + +Watch the commas to make sure it's valid json! Here's a few more config tips: + +
+Discord Bot Setup + +1. Create a new application at [Discord Developer Portal](https://discord.com/developers/applications) +2. Create a bot and get your token +3. Add bot to your server using OAuth2 URL generator +4. Set `DISCORD_API_TOKEN` and `DISCORD_APPLICATION_ID` in your `.env` +
+ +
+Twitter Integration + +Add to your `.env`: + +```bash +TWITTER_USERNAME= # Account username +TWITTER_PASSWORD= # Account password +TWITTER_EMAIL= # Account email +TWITTER_2FA_SECRET= # In order to avoid X preventing the login, it is better to activate 2fa in the target account, copy the 2fa secret and paste it here +``` + +**Important:** Log in to the [Twitter Developer Portal](https://developer.twitter.com) and enable the "Automated" label for your account to avoid being flagged as inauthentic. +
+ +
+Telegram Bot + +1. Create a bot +2. Add your bot token to `.env`: + +```bash +TELEGRAM_BOT_TOKEN=your_token_here +``` +
+ + + + +### GPU Acceleration + +If you have a Nvidia GPU you can enable CUDA support. First ensure CUDA Toolkit, cuDNN, and cuBLAS are first installed, then: `npx --no node-llama-cpp source download --gpu cuda` + + + +--- + +## FAQ + +### What's the difference between eliza and eliza-starter? +Eliza-starter is a lightweight version for simpler setups, while the main eliza repository includes all advanced features and a web client. + +### How do I fix build/installation issues? +Use Node v23.3.0, run `pnpm clean`, then `pnpm install --no-frozen-lockfile`, followed by `pnpm build`. If issues persist, checkout the latest stable tag. + +### What are the minimum system requirements? +8GB RAM recommended for build process. For deployment, a t2.large instance on AWS with 20GB storage running Ubuntu is the minimum tested configuration. + +### How do I fix "Exit Status 1" errors? +If you see `triggerUncaughtException` errors, try: +1. Add dependencies to workspace root +2. Add dependencies to specific packages +3. Clean and rebuild + +## Next Steps + +Once you have your agent running, explore: + +1. 🤖 [Understand Agents](./core/agents.md) +2. 📝 [Create Custom Characters](./core/characterfile.md) +3. ⚡ [Add Custom Actions](./core/actions.md) +4. 🔧 [Advanced Configuration](./guides/configuration.md) + +Join the [Discord community](https://discord.gg/elizaOS) for support and to share what you're building! +```` + +## File: .env.example +```` +# OpenAI Configuration +OPENAI_API_KEY= + +# Anthropic Configuration +ANTHROPIC_API_KEY= + +# Fill these out if you want to use Discord +DISCORD_APPLICATION_ID= +DISCORD_API_TOKEN= + +# Fill these out if you want to use Postgres +POSTGRES_URL= + +# Fill these out if you want to use Telegram +TELEGRAM_BOT_TOKEN= + +# Fill these out if you want to use Twitter +TWITTER_USERNAME= +TWITTER_PASSWORD= +TWITTER_EMAIL= + +# Fill these out if you want to use EVM +EVM_PRIVATE_KEY= +EVM_CHAINS=mainnet,sepolia,base,arbitrum,polygon +EVM_PROVIDER_URL= + +# Fill these out if you want to use Solana +SOLANA_PUBLIC_KEY= +SOLANA_PRIVATE_KEY= +BIRDEYE_API_KEY= + +# Local AI Configuration +USE_LOCAL_AI= +USE_STUDIOLM_TEXT_MODELS= +USE_OLLAMA_TEXT_MODELS= + +# Ollama Configuration +OLLAMA_SERVER_URL= +OLLAMA_MODEL= +USE_OLLAMA_EMBEDDING= +OLLAMA_EMBEDDING_MODEL= +SMALL_OLLAMA_MODEL= +MEDIUM_OLLAMA_MODEL= +LARGE_OLLAMA_MODEL= + +# StudioLM Configuration +STUDIOLM_SERVER_URL= +STUDIOLM_SMALL_MODEL= +STUDIOLM_MEDIUM_MODEL= +STUDIOLM_EMBEDDING_MODEL= + +# Settings for The Org + +COMMUNITY_MANAGER_DISCORD_APPLICATION_ID= +COMMUNITY_MANAGER_DISCORD_API_TOKEN= + +SOCIAL_MEDIA_MANAGER_DISCORD_APPLICATION_ID= +SOCIAL_MEDIA_MANAGER_DISCORD_API_TOKEN= + +LIAISON_DISCORD_APPLICATION_ID= +LIAISON_DISCORD_API_TOKEN= + +PROJECT_MANAGER_DISCORD_APPLICATION_ID= +PROJECT_MANAGER_DISCORD_API_TOKEN= + +DEV_REL_DISCORD_APPLICATION_ID= +DEV_REL_DISCORD_API_TOKEN= + +INVESTMENT_MANAGER_DISCORD_APPLICATION_ID= +INVESTMENT_MANAGER_DISCORD_API_TOKEN= + +# Settings for Investment Manager plugins +BIRDEYE_API_KEY= +JUPITER_API_KEY= +HELIUS_API_KEY= +COINMARKETCAP_API_KEY= +ZEROEX_API_KEY= +COINGECKO_API_KEY= +```` + +## File: package.json +````json +{ + "name": "eliza", + "scripts": { + "preinstall": "npx only-allow bun", + "start": "cd ./packages/the-org && bun run start", + "start:debug": "LOG_LEVEL=debug elizaos start", + "start:app": "turbo run start --filter=./packages/app", + "dev": "turbo run dev --filter=./packages/the-org", + "build:core": "turbo run build --filter=@elizaos/core --no-cache", + "build": "bun run build:core && turbo run build --filter=@elizaos/plugin-* --filter=@elizaos/client --no-cache && turbo run build --filter=!@elizaos/core --filter=!@elizaos/plugin-* --filter=!@elizaos/docs --no-cache", + "clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo bun.lock* && turbo run clean --filter=./packages/*", + "lint": "turbo run lint --filter=./packages/*", + "release": "bun run build && bun lint && lerna publish --no-private --force-publish && bun lint", + "release:alpha": "lerna publish prerelease --preid alpha --dist-tag alpha --no-private --force-publish --loglevel verbose", + "migrate": "turbo run migrate --filter=./packages/plugin-sql --force", + "migrate:generate": "turbo run migrate:generate --filter=./packages/plugin-sql", + "docker:build": "bash ./scripts/docker.sh build", + "docker:run": "bash ./scripts/docker.sh run", + "docker:bash": "bash ./scripts/docker.sh bash", + "docker:start": "bash ./scripts/docker.sh start", + "docker": "bun docker:build && bun docker:run && bun docker:bash", + "test": "turbo run test --concurrency 20 --filter=!./packages/plugin-starter --filter=!./packages/project-starter --filter=!./packages/the-org --filter=!./packages/docs --filter=!./packages/plugin-video-understanding", + "test:app": "turbo run test --concurrency 20 --filter=./packages/app" + }, + "devDependencies": { + "@types/bun": "latest", + "@types/node": "^22.13.10", + "@vitest/eslint-plugin": "1.0.1", + "bun": "1.2.2", + "concurrently": "9.1.0", + "cross-env": "7.0.3", + "husky": "9.1.7", + "lerna": "8.1.4", + "only-allow": "^1.2.1", + "sharp": "0.33.5", + "turbo": "^2.4.4", + "typedoc": "0.27.9", + "typescript": "5.8.2", + "vite": "5.4.12", + "vitest": "3.0.5", + "@types/uuid": "^9.0.8", + "tsup": "8.4.0" + }, + "bun": { + "overrides": { + "cookie": "0.7.0", + "bs58": "5.0.0", + "secp256k1": "5.0.1", + "minipass": "7.1.2", + "form-data": "4.0.2", + "eslint": "9.22.0", + "react": "19.0.0", + "react-dom": "19.0.0", + "got": "12.6.1" + } + }, + "engines": { + "node": "23.3.0" + }, + "dependencies": { + "@anthropic-ai/sdk": "^0.39.0", + "@babel/generator": "^7.26.9", + "vittest": "^1.0.2", + "zod": "3.24.1" + }, + "packageManager": "bun@1.2.2", + "workspaces": [ + "packages/*" + ], + "module": "index.ts", + "type": "module", + "resolutions": { + "@nrwl/devkit": "19.8.13", + "@nrwl/tao": "19.8.13", + "zod": "3.24.1", + "eslint": "9.22.0", + "react": "19.0.0", + "react-dom": "19.0.0", + "vitest": "3.0.5", + "@metaplex-foundation/umi": "0.9.2", + "typedoc-plugin-markdown": "4.2.10", + "buffer": "6.0.3", + "@solana/spl-token": "0.4.9", + "solana-bankrun": "0.3.1", + "got": "12.6.1", + "form-data": "4.0.2" + }, + "trustedDependencies": [ + "@elizaos/plugin-browser", + "@elizaos/plugin-pdf", + "@elizaos/plugin-storage-s3", + "@elizaos/plugin-video-understanding", + "@swc/core", + "better-sqlite3", + "bigint-buffer", + "bufferutil", + "bun", + "canvas", + "core-js", + "core-js-pure", + "cpu-features", + "es5-ext", + "esbuild", + "node-llama-cpp", + "nx", + "onnxruntime-node", + "protobufjs", + "sharp", + "ssh2", + "utf-8-validate" + ] +} +```` + +## File: README.md +````markdown +# Eliza 🤖 + +
+ Eliza Banner +
+ +
+ +📑 [Technical Report](https://arxiv.org/pdf/2501.06781) | 📖 [Documentation](https://elizaos.github.io/eliza/) | 🎯 [Examples](https://github.com/thejoven/awesome-eliza) + +
+ +## 🌍 README Translations + +[中文说明](packages/docs/i18n/readme/README_CN.md) | [日本語の説明](packages/docs/i18n/readme/README_JA.md) | [한국어 설명](packages/docs/i18n/readme/README_KOR.md) | [Persian](packages/docs/i18n/readme/README_FA.md) | [Français](packages/docs/i18n/readme/README_FR.md) | [Português](packages/docs/i18n/readme/README_PTBR.md) | [Türkçe](packages/docs/i18n/readme/README_TR.md) | [Русский](packages/docs/i18n/readme/README_RU.md) | [Español](packages/docs/i18n/readme/README_ES.md) | [Italiano](packages/docs/i18n/readme/README_IT.md) | [ไทย](packages/docs/i18n/readme/README_TH.md) | [Deutsch](packages/docs/i18n/readme/README_DE.md) | [Tiếng Việt](packages/docs/i18n/readme/README_VI.md) | [עִברִית](packages/docs/i18n/readme/README_HE.md) | [Tagalog](packages/docs/i18n/readme/README_TG.md) | [Polski](packages/docs/i18n/readme/README_PL.md) | [Arabic](packages/docs/i18n/readme/README_AR.md) | [Hungarian](packages/docs/i18n/readme/README_HU.md) | [Srpski](packages/docs/i18n/readme/README_RS.md) | [Română](packages/docs/i18n/readme/README_RO.md) | [Nederlands](packages/docs/i18n/readme/README_NL.md) | [Ελληνικά](packages/docs/i18n/readme/README_GR.md) + +## 🚩 Overview + +
+ Eliza Diagram +
+ +## ✨ Features + +- 🛠️ Full-featured Discord, X (Twitter) and Telegram connectors +- 🔗 Support for every model (Llama, Grok, OpenAI, Anthropic, Gemini, etc.) +- 👥 Multi-agent and room support +- 📚 Easily ingest and interact with your documents +- 💾 Retrievable memory and document store +- 🚀 Highly extensible - create your own actions and clients +- 📦 Just works! + +## Video Tutorials + +[AI Agent Dev School](https://www.youtube.com/watch?v=ArptLpQiKfI&list=PLx5pnFXdPTRzWla0RaOxALTSTnVq53fKL) + +## 🎯 Use Cases + +- 🤖 Chatbots +- 🕵️ Autonomous Agents +- 📈 Business Process Handling +- 🎮 Video Game NPCs +- 🧠 Trading + +## 🚀 Quick Start + +### Prerequisites + +- [Python 2.7+](https://www.python.org/downloads/) +- [Node.js 23+](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) +- [bun](https://bun.sh) + +> **Note for Windows Users:** [WSL 2](https://learn.microsoft.com/en-us/windows/wsl/install-manual) is required. + +### Use the Starter (Recommended) + +```bash +git clone https://github.com/elizaos/eliza-starter.git +cd eliza-starter +cp .env.example .env +bun i && bun run build && bun start +``` + +### Manually Start Eliza (Only recommended if you know what you are doing) + +#### Checkout the latest release + +```bash +# Clone the repository +git clone https://github.com/elizaos/eliza.git + +# This project iterates fast, so we recommend checking out the latest release +git checkout $(git describe --tags --abbrev=0) +# If the above doesn't checkout the latest release, this should work: +# git checkout $(git describe --tags `git rev-list --tags --max-count=1`) +``` + +#### Edit the .env file + +Copy .env.example to .env and fill in the appropriate values. + +``` +cp .env.example .env +``` + +Note: .env is optional. If you're planning to run multiple distinct agents, you can pass secrets through the character JSON + +#### Start Eliza + +Important! We now use Bun. If you are using npm, you will need to install Bun: +https://bun.sh/docs/installation + +```bash +bun install +bun run build # npm will work too +bun start # npm will work too +``` + +### Interact via Browser + +Once the agent is running, you should see the message to run "bun start:client" at the end. + +Open another terminal, move to the same directory, run the command below, then follow the URL to chat with your agent. + +```bash +bun start:client +``` + +Then read the [Documentation](https://elizaos.github.io/eliza/) to learn how to customize your Eliza. + +--- + +### Automatically Start Eliza + +The start script provides an automated way to set up and run Eliza: + +```bash +sh scripts/start.sh +``` + +For detailed instructions on using the start script, including character management and troubleshooting, see our [Start Script Guide](./docs/docs/guides/start-script.md). + +> **Note**: The start script handles all dependencies, environment setup, and character management automatically. + +--- + +### Modify Character + +1. Open `packages/core/src/defaultCharacter.ts` to modify the default character. Uncomment and edit. + +2. To load custom characters: + - Use `bun start --characters="path/to/your/character.json"` + - Multiple character files can be loaded simultaneously +3. Connect with X (Twitter) + - change `"clients": []` to `"clients": ["twitter"]` in the character file to connect with X + +--- + +#### Additional Requirements + +You may need to install Sharp. If you see an error when starting up, try installing it with the following command: + +``` +bun install --include=optional sharp +``` +--- + +### Deploy Eliza in one click + +Use [Fleek](https://fleek.xyz/eliza/) to deploy Eliza in one click. This opens Eliza to non-developers and provides the following options to build your agent: +1. Start with a template +2. Build characterfile from scratch +3. Upload pre-made characterfile + +Click [here](https://fleek.xyz/eliza/) to get started! + +--- + +### Community & contact + +- [GitHub Issues](https://github.com/elizaos/eliza/issues). Best for: bugs you encounter using Eliza, and feature proposals. +- [Discord](https://discord.gg/ai16z). Best for: sharing your applications and hanging out with the community. + +## Citation + +We now have a [paper](https://arxiv.org/pdf/2501.06781) you can cite for the Eliza OS: +```bibtex +@article{walters2025eliza, + title={Eliza: A Web3 friendly AI Agent Operating System}, + author={Walters, Shaw and Gao, Sam and Nerd, Shakker and Da, Feng and Williams, Warren and Meng, Ting-Chien and Han, Hunter and He, Frank and Zhang, Allen and Wu, Ming and others}, + journal={arXiv preprint arXiv:2501.06781}, + year={2025} +} +``` + +## Contributors + + + Eliza project contributors + + + +## Star History + +[![Star History Chart](https://api.star-history.com/svg?repos=elizaos/eliza&type=Date)](https://star-history.com/#elizaos/eliza&Date) +```` + + +# Instruction +# ElizaOS Developer Context + +This file contains the core technical aspects of ElizaOS, focusing on its architecture, implementation, and developer-facing components. The codebase is organized as a monorepo with several key packages: + +## Key Components + +1. **Core Package**: The foundation of ElizaOS with the agent runtime, entity management, actions, and database interactions +2. **CLI Package**: Command-line interface for managing agents, projects, and development tasks +3. **Client Package**: Frontend interface components and API interactions +4. **SQL/Database**: Database adapters and schema management +5. **Autodoc**: Documentation generation tools + +## Technical Goals + +When analyzing this codebase: + +- Focus on the architecture and relationships between components +- Identify core abstractions and design patterns +- Understand the runtime execution flow +- Analyze how agents, actions, and providers work together +- Look for opportunities to improve code organization and performance +- Consider modular extension points and plugin architecture + +## Output Guidance + +- When suggesting improvements, focus on technical aspects like code structure, performance optimizations, and architectural changes +- Include specific code examples when proposing changes +- Consider backwards compatibility and migration paths for any proposed changes +- Highlight innovative technical approaches used in the system +- When asked about implementation details, provide comprehensive technical explanations diff --git a/packages/plugin-anthropic/package.json b/packages/plugin-anthropic/package.json index e299f074886..ac063542e80 100644 --- a/packages/plugin-anthropic/package.json +++ b/packages/plugin-anthropic/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/plugin-anthropic", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "type": "module", "main": "dist/index.js", "module": "dist/index.js", @@ -23,7 +23,7 @@ ], "dependencies": { "@ai-sdk/anthropic": "^1.1.6", - "@elizaos/core": "^1.0.0-beta.2", + "@elizaos/core": "^1.0.0-beta.7", "fastembed": "^1.0.0", "tsup": "8.4.0" }, @@ -47,7 +47,7 @@ } } }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55", + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e", "devDependencies": { "prettier": "3.5.3" } diff --git a/packages/plugin-browser/package.json b/packages/plugin-browser/package.json index a12d327dbe7..dae5f2d8097 100644 --- a/packages/plugin-browser/package.json +++ b/packages/plugin-browser/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/plugin-browser", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "type": "module", "main": "dist/index.js", "module": "dist/index.js", @@ -28,7 +28,7 @@ "dependencies": { "@aws-sdk/client-s3": "^3.705.0", "@aws-sdk/s3-request-presigner": "^3.705.0", - "@elizaos/core": "^1.0.0-beta.2", + "@elizaos/core": "^1.0.0-beta.7", "@types/uuid": "10.0.0", "capsolver-npm": "2.0.2", "fluent-ffmpeg": "2.1.3", @@ -57,5 +57,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55" + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e" } diff --git a/packages/plugin-discord/package.json b/packages/plugin-discord/package.json index fd2b497007c..5147c9589bd 100644 --- a/packages/plugin-discord/package.json +++ b/packages/plugin-discord/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/plugin-discord", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "type": "module", "main": "dist/index.js", "module": "dist/index.js", @@ -49,5 +49,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55" + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e" } diff --git a/packages/plugin-elevenlabs/package.json b/packages/plugin-elevenlabs/package.json index 92a7294496b..3d753b1809e 100644 --- a/packages/plugin-elevenlabs/package.json +++ b/packages/plugin-elevenlabs/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/plugin-elevenlabs", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "type": "module", "main": "dist/index.js", "module": "dist/index.js", @@ -22,7 +22,7 @@ "dist" ], "dependencies": { - "@elizaos/core": "^1.0.0-beta.2", + "@elizaos/core": "^1.0.0-beta.7", "tsup": "8.4.0" }, "scripts": { @@ -77,7 +77,7 @@ } } }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55", + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e", "devDependencies": { "prettier": "3.5.3" } diff --git a/packages/plugin-evm/package.json b/packages/plugin-evm/package.json index e2b68b86362..1ff60bc2bd7 100644 --- a/packages/plugin-evm/package.json +++ b/packages/plugin-evm/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/plugin-evm", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "type": "module", "main": "dist/index.js", "module": "dist/index.js", @@ -22,7 +22,7 @@ "dist" ], "dependencies": { - "@elizaos/plugin-tee": "^1.0.0-beta.2", + "@elizaos/plugin-tee": "^1.0.0-beta.7", "@lifi/data-types": "5.15.5", "@lifi/sdk": "3.4.1", "@lifi/types": "16.3.0", @@ -53,5 +53,5 @@ } } }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55" + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e" } diff --git a/packages/plugin-groq/.gitignore b/packages/plugin-groq/.gitignore new file mode 100644 index 00000000000..77738287f0e --- /dev/null +++ b/packages/plugin-groq/.gitignore @@ -0,0 +1 @@ +dist/ \ No newline at end of file diff --git a/packages/plugin-groq/.npmignore b/packages/plugin-groq/.npmignore new file mode 100644 index 00000000000..078562eceab --- /dev/null +++ b/packages/plugin-groq/.npmignore @@ -0,0 +1,6 @@ +* + +!dist/** +!package.json +!readme.md +!tsup.config.ts \ No newline at end of file diff --git a/packages/plugin-groq/README.md b/packages/plugin-groq/README.md new file mode 100644 index 00000000000..dbad16b35ac --- /dev/null +++ b/packages/plugin-groq/README.md @@ -0,0 +1,85 @@ +# OpenAI Plugin + +This plugin provides integration with OpenAI's models through the ElizaOS platform. + +## Usage + +Add the plugin to your character configuration: + +```json +"plugins": ["@elizaos/plugin-openai"] +``` + +## Configuration + +The plugin requires these environment variables (can be set in .env file or character settings): + +```json +"settings": { + "OPENAI_API_KEY": "your_openai_api_key", + "OPENAI_BASE_URL": "optional_custom_endpoint", + "OPENAI_SMALL_MODEL": "gpt-4o-mini", + "OPENAI_LARGE_MODEL": "gpt-4o" +} +``` + +Or in `.env` file: + +``` +OPENAI_API_KEY=your_openai_api_key +# Optional overrides: +OPENAI_BASE_URL=optional_custom_endpoint +OPENAI_SMALL_MODEL=gpt-4o-mini +OPENAI_LARGE_MODEL=gpt-4o +``` + +### Configuration Options + +- `OPENAI_API_KEY` (required): Your OpenAI API credentials +- `OPENAI_BASE_URL`: Custom API endpoint (default: https://api.openai.com/v1) +- `OPENAI_SMALL_MODEL`: Defaults to GPT-4o Mini ("gpt-4o-mini") +- `OPENAI_LARGE_MODEL`: Defaults to GPT-4o ("gpt-4o") + +The plugin provides these model classes: + +- `TEXT_SMALL`: Optimized for fast, cost-effective responses +- `TEXT_LARGE`: For complex tasks requiring deeper reasoning +- `TEXT_EMBEDDING`: Text embedding model (text-embedding-3-small) +- `IMAGE`: DALL-E image generation +- `IMAGE_DESCRIPTION`: GPT-4o image analysis +- `TRANSCRIPTION`: Whisper audio transcription +- `TEXT_TOKENIZER_ENCODE`: Text tokenization +- `TEXT_TOKENIZER_DECODE`: Token decoding + +## Additional Features + +### Image Generation + +```js +await runtime.useModel(ModelType.IMAGE, { + prompt: 'A sunset over mountains', + n: 1, // number of images + size: '1024x1024', // image resolution +}); +``` + +### Audio Transcription + +```js +const transcription = await runtime.useModel(ModelType.TRANSCRIPTION, audioBuffer); +``` + +### Image Analysis + +```js +const { title, description } = await runtime.useModel( + ModelType.IMAGE_DESCRIPTION, + 'https://example.com/image.jpg' +); +``` + +### Text Embeddings + +```js +const embedding = await runtime.useModel(ModelType.TEXT_EMBEDDING, 'text to embed'); +``` diff --git a/packages/plugin-groq/package.json b/packages/plugin-groq/package.json new file mode 100644 index 00000000000..d49ee748d59 --- /dev/null +++ b/packages/plugin-groq/package.json @@ -0,0 +1,56 @@ +{ + "name": "@elizaos/plugin-groq", + "version": "1.0.0-beta.2", + "type": "module", + "main": "dist/index.js", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/elizaos-plugins/plugin-groq" + }, + "exports": { + "./package.json": "./package.json", + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + } + }, + "files": [ + "dist" + ], + "dependencies": { + "@ai-sdk/groq": "^1.1.9", + "@ai-sdk/ui-utils": "1.1.9", + "@elizaos/core": "workspace:*", + "ai": "^4.1.25", + "js-tiktoken": "^1.0.18", + "tsup": "8.4.0" + }, + "scripts": { + "build": "tsup", + "dev": "tsup --watch", + "lint": "prettier --write ./src", + "clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo", + "format": "prettier --write ./src", + "format:check": "prettier --check ./src" + }, + "publishConfig": { + "access": "public" + }, + "agentConfig": { + "pluginType": "elizaos:plugin:1.0.0", + "pluginParameters": { + "GROQ_API_KEY": { + "type": "string", + "description": "API key for the service" + } + } + }, + "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55", + "devDependencies": { + "prettier": "3.5.3" + } +} diff --git a/packages/plugin-groq/src/index.ts b/packages/plugin-groq/src/index.ts new file mode 100644 index 00000000000..ed0a407a3ee --- /dev/null +++ b/packages/plugin-groq/src/index.ts @@ -0,0 +1,791 @@ +import { createGroq } from '@ai-sdk/groq'; +//import Groq from "groq-sdk"; +import type { + ImageDescriptionParams, + ModelTypeName, + ObjectGenerationParams, + Plugin, + TextEmbeddingParams, +} from '@elizaos/core'; +import { + type DetokenizeTextParams, + type GenerateTextParams, + ModelType, + type TokenizeTextParams, + logger, +} from '@elizaos/core'; +import { generateObject, generateText } from 'ai'; +import { type TiktokenModel, encodingForModel } from 'js-tiktoken'; +import { z } from 'zod'; + +/** + * Gets the Cloudflare Gateway base URL for a specific provider if enabled + * @param runtime The runtime environment + * @param provider The model provider name + * @returns The Cloudflare Gateway base URL if enabled, undefined otherwise + */ +function getCloudflareGatewayBaseURL(runtime: any, provider: string): string | undefined { + const isCloudflareEnabled = runtime.getSetting('CLOUDFLARE_GW_ENABLED') === 'true'; + const cloudflareAccountId = runtime.getSetting('CLOUDFLARE_AI_ACCOUNT_ID'); + const cloudflareGatewayId = runtime.getSetting('CLOUDFLARE_AI_GATEWAY_ID'); + + const defaultUrl = 'https://api.groq.com/openai/v1'; + logger.debug('Cloudflare Gateway Configuration:', { + isEnabled: isCloudflareEnabled, + hasAccountId: !!cloudflareAccountId, + hasGatewayId: !!cloudflareGatewayId, + provider: provider, + }); + + if (!isCloudflareEnabled) { + logger.debug('Cloudflare Gateway is not enabled'); + return defaultUrl; + } + + if (!cloudflareAccountId) { + logger.warn('Cloudflare Gateway is enabled but CLOUDFLARE_AI_ACCOUNT_ID is not set'); + return defaultUrl; + } + + if (!cloudflareGatewayId) { + logger.warn('Cloudflare Gateway is enabled but CLOUDFLARE_AI_GATEWAY_ID is not set'); + return defaultUrl; + } + + const baseURL = `https://gateway.ai.cloudflare.com/v1/${cloudflareAccountId}/${cloudflareGatewayId}/${provider.toLowerCase()}`; + logger.info('Using Cloudflare Gateway:', { + provider, + baseURL, + accountId: cloudflareAccountId, + gatewayId: cloudflareGatewayId, + }); + + return baseURL; +} + +/** + * Asynchronously tokenizes the given text based on the specified model and prompt. + * + * @param {ModelTypeName} model - The type of model to use for tokenization. + * @param {string} prompt - The text prompt to tokenize. + * @returns {number[]} - An array of tokens representing the encoded prompt. + +GROQ_API_KEY= +EMBEDDING_GROQ_MODEL=llama-3.1-8b-instant +LARGE_GROQ_MODEL=llama-3.2-90b-vision-preview +MEDIUM_GROQ_MODEL=llama-3.3-70b-versatile +SMALL_GROQ_MODEL=llama-3.1-8b-instant + +*/ + +function findModelName(model: ModelTypeName): TiktokenModel { + const name = + model === ModelType.TEXT_SMALL + ? (process.env.SMALL_GROQ_MODEL ?? 'llama-3.1-8b-instant') + : (process.env.LARGE_GROQ_MODEL ?? 'llama-3.2-90b-vision-preview'); + return name as TiktokenModel; +} +async function tokenizeText(model: ModelTypeName, prompt: string) { + const encoding = encodingForModel(findModelName(model)); + const tokens = encoding.encode(prompt); + return tokens; +} + +/** + * Detokenize a sequence of tokens back into text using the specified model. + * + * @param {ModelTypeName} model - The type of model to use for detokenization. + * @param {number[]} tokens - The sequence of tokens to detokenize. + * @returns {string} The detokenized text. + */ +async function detokenizeText(model: ModelTypeName, tokens: number[]) { + const modelName = findModelName(model); + const encoding = encodingForModel(modelName); + return encoding.decode(tokens); +} + +/** + * Defines the Groq plugin with its name, description, and configuration options. + * @type {Plugin} + * + * logger.debug( + "Initializing Groq model with Cloudflare check" + ); + const baseURL = getCloudflareGatewayBaseURL(runtime, "groq"); + logger.debug("Groq baseURL result:", { baseURL }); + const groq = createGroq({ + apiKey, + fetch: runtime.fetch, + baseURL, + }); + + const { text: groqResponse } = await aiGenerateText({ + model: groq.languageModel(model), + prompt: context, + temperature, + system: + runtime.character.system ?? + settings.SYSTEM_PROMPT ?? + undefined, + tools, + onStepFinish: onStepFinish, + maxSteps, + maxTokens: max_response_length, + frequencyPenalty: frequency_penalty, + presencePenalty: presence_penalty, + experimental_telemetry, + }); + + response = groqResponse; + logger.debug("Received response from Groq model."); + + break; + } + async function handleGroq({ + model, + apiKey, + schema, + schemaName, + schemaDescription, + mode = "json", + modelOptions, + runtime, +}: ProviderOptions): Promise { + logger.debug("Handling Groq request with Cloudflare check"); + const baseURL = getCloudflareGatewayBaseURL(runtime, "groq"); + logger.debug("Groq handleGroq baseURL:", { baseURL }); + + + const groq = createGroq({ + apiKey, + baseURL, + fetch: runtime.fetch + }); + return await aiGenerateObject({ + model: groq.languageModel(model), + schema, + schemaName, + schemaDescription, + mode, + ...modelOptions, + }); +} + */ +export const groqPlugin: Plugin = { + name: 'groq', + description: 'Groq plugin', + config: { + GROQ_API_KEY: process.env.GROQ_API_KEY, + SMALL_GROQ_MODEL: process.env.SMALL_GROQ_MODEL, + MEDIUM_GROQ_MODEL: process.env.MEDIUM_GROQ_MODEL, + LARGE_GROQ_MODEL: process.env.LARGE_GROQ_MODEL, + }, + async init(config: Record) { + //try { + // const validatedConfig = await configSchema.parseAsync(config); + + // // Set all environment variables at once + // for (const [key, value] of Object.entries(validatedConfig)) { + // if (value) process.env[key] = value; + // } + + // If API key is not set, we'll show a warning but continue + if (!process.env.GROQ_API_KEY) { + throw Error('Missing GROQ_API_KEY in environment variables'); + } + + // // Verify API key only if we have one + // try { + // //const baseURL = process.env.GROQ_BASE_URL ?? 'https://api.openai.com/v1'; + // const response = await fetch(`${baseURL}/models`, { + // headers: { Authorization: `Bearer ${process.env.GROQ_API_KEY}` }, + // //const baseURL = process.env.OPENAI_BASE_URL ?? 'https://api.openai.com/v1'; + // const response = await fetch(`${baseURL}/models`, { + // headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` }, + // //const baseURL = process.env.GROQ_BASE_URL ?? 'https://api.openai.com/v1'; + // const response = await fetch(`${baseURL}/models`, { + // headers: { Authorization: `Bearer ${process.env.GROQ_API_KEY}` }, + // }); + // if (!response.ok) { + // logger.warn(`OpenAI API key validation failed: ${response.statusText}`); + // logger.warn('OpenAI functionality will be limited until a valid API key is provided'); + // // Continue execution instead of throwing + // } else { + // // logger.log("OpenAI API key validated successfully"); + // } + // } catch (fetchError) { + // logger.warn(`Error validating OpenAI API key: ${fetchError}`); + // logger.warn('OpenAI functionality will be limited until a valid API key is provided'); + // // Continue execution instead of throwing + // } + // } catch (error) { + // // Convert to warning instead of error + // logger.warn( + // `OpenAI plugin configuration issue: ${error.errors + // .map((e) => e.message) + // .join(', ')} - You need to configure the GROQ_API_KEY in your environment variables` + // .join(', ')} - You need to configure the OPENAI_API_KEY in your environment variables` + // .join(', ')} - You need to configure the GROQ_API_KEY in your environment variables` + // ); + // } + }, + models: { + [ModelType.TEXT_EMBEDDING]: async ( + runtime, + params: TextEmbeddingParams | string | null + ): Promise => { + // Handle null input (initialization case) + //if (params === null) { + //logger.debug('Creating test embedding for initialization'); + // Return a consistent vector for null input + const testVector = Array(1536).fill(0); + testVector[0] = 0.1; // Make it non-zero + return testVector; + //} + + // // Get the text from whatever format was provided + // let text: string; + // if (typeof params === 'string') { + // text = params; // Direct string input + // } else if (typeof params === 'object' && params.text) { + // text = params.text; // Object with text property + // } else { + // logger.warn('Invalid input format for embedding'); + // // Return a fallback for invalid input + // const fallbackVector = Array(1536).fill(0); + // fallbackVector[0] = 0.2; // Different value for tracking + // return fallbackVector; + // } + + // // Skip API call for empty text + // if (!text.trim()) { + // logger.warn('Empty text for embedding'); + // const emptyVector = Array(1536).fill(0); + // emptyVector[0] = 0.3; // Different value for tracking + // return emptyVector; + // } + + // // truncate + // console.log('INPUT PROMPT:', text); + // if (text.length > 8000) { + // text = text.substring(0, 8000); + // console.log('TRUNCATED PROMPT', text); + // } + + // const baseURL = getCloudflareGatewayBaseURL(runtime, 'groq'); + // const data4 = { + // method: 'GET', + // headers: { + // Authorization: `Bearer ${process.env.GROQ_API_KEY}`, + // 'Content-Type': 'application/json', + // } + // }; + // const response2 = await fetch(`${baseURL}/models`, data4); + // if (!response2.ok) { + // logger.error(`GROQ error: ${response2.status} - ${response2.statusText}`); + // const errorVector = Array(1536).fill(0); + // errorVector[0] = 0.4; // Different value for tracking + // return errorVector; + // } + // const models = (await response2.json()) as { data: { id: string }[] } + // console.log(models); + // console.log('MODELS:', models); + // //getModels().then((models) => + + // //console.log(models); + // models.data.forEach(async (model) => { + // console.log("MODEL", model); + // console.log(model.id) + // const data1 = { + // method: 'POST', + // headers: { + // Authorization: `Bearer ${process.env.GROQ_API_KEY}`, + // 'Content-Type': 'application/json', + // }, + // body: JSON.stringify({ + // model: model.id, + // input: text, + // }), + // }; + // console.log('DATA', data1); + // const response = await fetch(`${baseURL}/embeddings`, data1); + // if (!response.ok) { + // console.log("response", response) + // logger.error(`GROQ error: ${response.status} - ${response.statusText}`); + // const errorVector = Array(1536).fill(0); + // errorVector[0] = 0.4; // Different value for tracking + // return errorVector; + // } + // const data = (await response.json()) as { + // data: [{ embedding: number[] }]; + // }; + // if (!data?.data?.[0]?.embedding) { + // logger.error('API returned invalid structure'); + // const errorVector = Array(1536).fill(0); + // errorVector[0] = 0.5; // Different value for tracking + // return errorVector; + // } + // const embedding = data.data[0].embedding; + // logger.log(`Got valid embedding with length ${embedding.length}`); + // return embedding; + // }) + //const errorVector = Array(1536).fill(0); + //errorVector[0] = 0.6; // Different value for tracking + //return errorVector; + }, + [ModelType.TEXT_TOKENIZER_ENCODE]: async ( + _runtime, + { prompt, modelType = ModelType.TEXT_LARGE }: TokenizeTextParams + ) => { + return await tokenizeText(modelType ?? ModelType.TEXT_LARGE, prompt); + }, + [ModelType.TEXT_TOKENIZER_DECODE]: async ( + _runtime, + { tokens, modelType = ModelType.TEXT_LARGE }: DetokenizeTextParams + ) => { + return await detokenizeText(modelType ?? ModelType.TEXT_LARGE, tokens); + }, + [ModelType.TEXT_SMALL]: async (runtime, { prompt, stopSequences = [] }: GenerateTextParams) => { + const temperature = 0.7; + const frequency_penalty = 0.7; + const presence_penalty = 0.7; + const max_response_length = 8000; + const baseURL = getCloudflareGatewayBaseURL(runtime, 'groq'); + const groq = createGroq({ + apiKey: runtime.getSetting('GROQ_API_KEY'), + fetch: runtime.fetch, + baseURL, + }); + + const model = + runtime.getSetting('GROQ_SMALL_MODEL') ?? + runtime.getSetting('SMALL_MODEL') ?? + 'llama-3.1-8b-instant'; + + logger.log('generating text'); + logger.log(prompt); + + const { text: openaiResponse } = await generateText({ + model: groq.languageModel(model), + prompt: prompt, + system: runtime.character.system ?? undefined, + temperature: temperature, + maxTokens: max_response_length, + //max_tokens: 300, + frequencyPenalty: frequency_penalty, + presencePenalty: presence_penalty, + stopSequences: stopSequences, + }); + + return openaiResponse; + }, + [ModelType.TEXT_LARGE]: async ( + runtime, + { + prompt, + stopSequences = [], + maxTokens = 8192, + temperature = 0.7, + frequencyPenalty = 0.7, + presencePenalty = 0.7, + }: GenerateTextParams + ) => { + const model = + runtime.getSetting('GROQ_LARGE_MODEL') ?? runtime.getSetting('LARGE_MODEL') ?? 'gpt-4444o'; + const baseURL = getCloudflareGatewayBaseURL(runtime, 'groq'); + const groq = createGroq({ + apiKey: runtime.getSetting('GROQ_API_KEY'), + fetch: runtime.fetch, + baseURL, + }); + const { text: openaiResponse } = await generateText({ + model: groq.languageModel(model), + prompt: prompt, + system: runtime.character.system ?? undefined, + temperature: temperature, + maxTokens: maxTokens, + frequencyPenalty: frequencyPenalty, + presencePenalty: presencePenalty, + stopSequences: stopSequences, + }); + return openaiResponse; + }, + [ModelType.IMAGE]: async ( + runtime, + params: { + prompt: string; + n?: number; + size?: string; + } + ) => { + const baseURL = getCloudflareGatewayBaseURL(runtime, 'groq'); + const response = await fetch(`${baseURL}/images/generations`, { + method: 'POST', + headers: { + Authorization: `Bearer ${runtime.getSetting('GROQ_API_KEY')}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + prompt: params.prompt, + n: params.n || 1, + size: params.size || '1024x1024', + }), + }); + if (!response.ok) { + throw new Error(`Failed to generate image: ${response.statusText}`); + } + const data = await response.json(); + const typedData = data as { data: { url: string }[] }; + return typedData.data; + }, + // [ModelType.IMAGE_DESCRIPTION]: async (runtime, params: ImageDescriptionParams | string) => { + // // Handle string case (direct URL) + // let imageUrl: string; + // let prompt: string | undefined; + + // if (typeof params === 'string') { + // imageUrl = params; + // prompt = undefined; + // } else { + // // Object parameter case + // imageUrl = params.imageUrl; + // prompt = params.prompt; + // } + + // try { + // const baseURL = getCloudflareGatewayBaseURL(runtime, 'groq'); + + // const apiKey = process.env.GROQ_API_KEY; + + // if (!apiKey) { + // logger.error('Groq API key not set'); + + // const baseURL = getCloudflareGatewayBaseURL(runtime, 'groq'); + + // const apiKey = process.env.GROQ_API_KEY; + + // if (!apiKey) { + // logger.error('Groq API key not set'); + // return { + // title: 'Failed to analyze image', + // description: 'API key not configured', + // }; + // } + + // // Call the GPT-4 Vision API + // const response = await fetch(`${baseURL}/chat/completions`, { + // method: 'POST', + // headers: { + // 'Content-Type': 'application/json', + // Authorization: `Bearer ${apiKey}`, + // }, + // body: JSON.stringify({ + // model: 'gpt-4-vision-preview', + // messages: [ + // { + // role: 'user', + // content: [ + // { + // type: 'text', + // text: + // prompt || + // 'Please analyze this image and provide a title and detailed description.', + // }, + // { + // type: 'image_url', + // image_url: { url: imageUrl }, + // }, + // ], + // }, + // ], + // max_tokens: 300, + // }), + // }); + + // if (!response.ok) { + // throw new Error(`OpenAI API error: ${response.status}`); + // } + + // const result: any = await response.json(); + // const content = result.choices?.[0]?.message?.content; + + // if (!content) { + // return { + // title: 'Failed to analyze image', + // description: 'No response from API', + // }; + // } + + // // Extract title and description + // const titleMatch = content.match(/title[:\s]+(.+?)(?:\n|$)/i); + // const title = titleMatch?.[1] || 'Image Analysis'; + + // // Rest of content is the description + // const description = content.replace(/title[:\s]+(.+?)(?:\n|$)/i, '').trim(); + // return { title, description }; + + // } + // }, + [ModelType.TRANSCRIPTION]: async (runtime, audioBuffer: Buffer) => { + logger.log('audioBuffer', audioBuffer); + const baseURL = getCloudflareGatewayBaseURL(runtime, 'groq'); + + const formData = new FormData(); + formData.append('file', new Blob([audioBuffer], { type: 'audio/mp3' })); + formData.append('model', 'whisper-1'); + const response = await fetch(`${baseURL}/audio/transcriptions`, { + method: 'POST', + headers: { + Authorization: `Bearer ${runtime.getSetting('GROQ_API_KEY')}`, + // Note: Do not set a Content-Type header—letting fetch set it for FormData is best + }, + body: formData, + }); + + logger.log('response', response); + if (!response.ok) { + throw new Error(`Failed to transcribe audio: ${response.statusText}`); + } + const data = (await response.json()) as { text: string }; + return data.text; + }, + [ModelType.OBJECT_SMALL]: async (runtime, params: ObjectGenerationParams) => { + const baseURL = getCloudflareGatewayBaseURL(runtime, 'groq'); + const groq = createGroq({ + apiKey: runtime.getSetting('GROQ_API_KEY'), + baseURL, + }); + const model = + runtime.getSetting('GROQ_SMALL_MODEL') ?? + runtime.getSetting('SMALL_MODEL') ?? + 'llama-3.1-8b-instangt'; + + try { + if (params.schema) { + // Skip zod validation and just use the generateObject without schema + logger.info('Using OBJECT_SMALL without schema validation'); + const { object } = await generateObject({ + model: groq.languageModel(model), + output: 'no-schema', + prompt: params.prompt, + temperature: params.temperature, + }); + return object; + } + + const { object } = await generateObject({ + model: groq.languageModel(model), + output: 'no-schema', + prompt: params.prompt, + temperature: params.temperature, + }); + return object; + } catch (error) { + logger.error('Error generating object:', error); + throw error; + } + }, + [ModelType.OBJECT_LARGE]: async (runtime, params: ObjectGenerationParams) => { + const baseURL = getCloudflareGatewayBaseURL(runtime, 'groq'); + const groq = createGroq({ + apiKey: runtime.getSetting('GROQ_API_KEY'), + //baseURL, + }); + const model = + runtime.getSetting('GROQ_LARGE_MODEL') ?? + runtime.getSetting('LARGE_MODEL') ?? + 'llama-3.2-90b-vision-preview'; + + try { + if (params.schema) { + // Skip zod validation and just use the generateObject without schema + logger.info('Using OBJECT_LARGE without schema validation'); + const { object } = await generateObject({ + model: groq.languageModel(model), + output: 'no-schema', + prompt: params.prompt, + temperature: params.temperature, + }); + return object; + } + + const { object } = await generateObject({ + model: groq.languageModel(model), + output: 'no-schema', + prompt: params.prompt, + temperature: params.temperature, + }); + return object; + } catch (error) { + logger.error('Error generating object:', error); + throw error; + } + }, + }, + // tests: [ + // { + // name: 'openai_plugin_tests', + // tests: [ + // { + // name: 'openai_test_url_and_api_key_validation', + // fn: async (runtime) => { + // const baseURL = getCloudflareGatewayBaseURL(runtime, 'groq'); + // const response = await fetch(`${baseURL}/models`, { + // headers: { + // Authorization: `Bearer ${runtime.getSetting('GROQ_API_KEY')}`, + // }, + // }); + // const data = await response.json(); + // logger.log('Models Available:', (data as any)?.data.length); + // if (!response.ok) { + // throw new Error(`Failed to validate OpenAI API key: ${response.statusText}`); + // } + // }, + // }, + // // { + // // name: 'groq_test_text_embedding', + // // fn: async (runtime) => { + // // try { + // // const embedding = await runtime.useModel(ModelType.TEXT_EMBEDDING, { + // // text: 'Hello, world!', + // // }); + // // logger.log('embedding', embedding); + // // } catch (error) { + // // logger.error('Error in test_text_embedding:', error); + // // throw error; + // // } + // // }, + // // }, + // { + // name: 'openai_test_text_large', + // fn: async (runtime) => { + // try { + // const text = await runtime.useModel(ModelType.TEXT_LARGE, { + // prompt: 'What is the nature of reality in 10 words?', + // }); + // if (text.length === 0) { + // throw new Error('Failed to generate text'); + // } + // logger.log('generated with test_text_large:', text); + // } catch (error) { + // logger.error('Error in test_text_large:', error); + // throw error; + // } + // }, + // }, + // { + // name: 'openai_test_text_small', + // fn: async (runtime) => { + // try { + // const text = await runtime.useModel(ModelType.TEXT_SMALL, { + // prompt: 'What is the nature of reality in 10 words?', + // }); + // if (text.length === 0) { + // throw new Error('Failed to generate text'); + // } + // logger.log('generated with test_text_small:', text); + // } catch (error) { + // logger.error('Error in test_text_small:', error); + // throw error; + // } + // }, + // }, + // { + // name: 'openai_test_image_generation', + // fn: async (runtime) => { + // logger.log('openai_test_image_generation'); + // try { + // const image = await runtime.useModel(ModelType.IMAGE, { + // prompt: 'A beautiful sunset over a calm ocean', + // n: 1, + // size: '1024x1024', + // }); + // logger.log('generated with test_image_generation:', image); + // } catch (error) { + // logger.error('Error in test_image_generation:', error); + // throw error; + // } + // }, + // }, + // { + // name: 'image-description', + // fn: async (runtime) => { + // try { + // logger.log('openai_test_image_description'); + // try { + // const result = await runtime.useModel( + // ModelType.IMAGE_DESCRIPTION, + // 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg/537px-Vitalik_Buterin_TechCrunch_London_2015_%28cropped%29.jpg' + // ); + + // // Check if result has the expected structure + // if ( + // result && + // typeof result === 'object' && + // 'title' in result && + // 'description' in result + // ) { + // logger.log('Image description:', result); + // } else { + // logger.error('Invalid image description result format:', result); + // } + // } catch (e) { + // logger.error('Error in image description test:', e); + // } + // } catch (e) { + // logger.error('Error in openai_test_image_description:', e); + // } + // }, + // }, + // { + // name: 'openai_test_transcription', + // fn: async (runtime) => { + // logger.log('openai_test_transcription'); + // try { + // const response = await fetch( + // 'https://upload.wikimedia.org/wikipedia/en/4/40/Chris_Benoit_Voice_Message.ogg' + // ); + // const arrayBuffer = await response.arrayBuffer(); + // const transcription = await runtime.useModel( + // ModelType.TRANSCRIPTION, + // Buffer.from(new Uint8Array(arrayBuffer)) + // ); + // logger.log('generated with test_transcription:', transcription); + // } catch (error) { + // logger.error('Error in test_transcription:', error); + // throw error; + // } + // }, + // }, + // { + // name: 'openai_test_text_tokenizer_encode', + // fn: async (runtime) => { + // const prompt = 'Hello tokenizer encode!'; + // const tokens = await runtime.useModel(ModelType.TEXT_TOKENIZER_ENCODE, { prompt }); + // if (!Array.isArray(tokens) || tokens.length === 0) { + // throw new Error('Failed to tokenize text: expected non-empty array of tokens'); + // } + // logger.log('Tokenized output:', tokens); + // }, + // }, + // { + // name: 'openai_test_text_tokenizer_decode', + // fn: async (runtime) => { + // const prompt = 'Hello tokenizer decode!'; + // // Encode the string into tokens first + // const tokens = await runtime.useModel(ModelType.TEXT_TOKENIZER_ENCODE, { prompt }); + // // Now decode tokens back into text + // const decodedText = await runtime.useModel(ModelType.TEXT_TOKENIZER_DECODE, { tokens }); + // if (decodedText !== prompt) { + // throw new Error( + // `Decoded text does not match original. Expected "${prompt}", got "${decodedText}"` + // ); + // } + // logger.log('Decoded text:', decodedText); + // }, + // }, + // ], + // }, + // ], +}; +export default groqPlugin; diff --git a/packages/plugin-groq/tsconfig.build.json b/packages/plugin-groq/tsconfig.build.json new file mode 100644 index 00000000000..625391d02b2 --- /dev/null +++ b/packages/plugin-groq/tsconfig.build.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist", + "sourceMap": true, + "inlineSources": true, + "declaration": true, + "emitDeclarationOnly": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] +} diff --git a/packages/plugin-groq/tsconfig.json b/packages/plugin-groq/tsconfig.json new file mode 100644 index 00000000000..c22f2f30ce7 --- /dev/null +++ b/packages/plugin-groq/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "baseUrl": "../..", + "lib": ["ESNext"], + "target": "ESNext", + "module": "Preserve", + "moduleResolution": "Bundler", + "strict": false, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": false, + "allowImportingTsExtensions": true, + "declaration": true, + "emitDeclarationOnly": true, + "resolveJsonModule": true, + "noImplicitAny": false, + "allowJs": true, + "checkJs": false, + "noEmitOnError": false, + "moduleDetection": "force", + "allowArbitraryExtensions": true, + "paths": { + "@elizaos/core": ["../core/src"], + "@elizaos/core/*": ["../core/src/*"] + } + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/plugin-groq/tsup.config.ts b/packages/plugin-groq/tsup.config.ts new file mode 100644 index 00000000000..0fc4943587c --- /dev/null +++ b/packages/plugin-groq/tsup.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from 'tsup'; + +export default defineConfig({ + entry: ['src/index.ts'], + outDir: 'dist', + tsconfig: './tsconfig.build.json', // Use build-specific tsconfig + sourcemap: true, + clean: true, + format: ['esm'], // Ensure you're targeting CommonJS + dts: false, // Skip DTS generation to avoid external import issues // Ensure you're targeting CommonJS + external: [ + 'dotenv', // Externalize dotenv to prevent bundling + 'fs', // Externalize fs to use Node.js built-in module + 'path', // Externalize other built-ins if necessary + 'https', + 'http', + '@elizaos/core', + 'zod', + ], +}); diff --git a/packages/plugin-groq/vitest.config.ts b/packages/plugin-groq/vitest.config.ts new file mode 100644 index 00000000000..8e730d5055c --- /dev/null +++ b/packages/plugin-groq/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + }, +}); diff --git a/packages/plugin-local-ai/package.json b/packages/plugin-local-ai/package.json index ac96c1ada49..164532037f6 100644 --- a/packages/plugin-local-ai/package.json +++ b/packages/plugin-local-ai/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/plugin-local-ai", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "type": "module", "main": "dist/index.js", "module": "dist/index.js", @@ -22,7 +22,7 @@ "dist" ], "dependencies": { - "@elizaos/core": "^1.0.0-beta.2", + "@elizaos/core": "^1.0.0-beta.7", "@huggingface/hub": "^1.0.1", "@huggingface/inference": "^3.3.4", "@huggingface/transformers": "^3.3.3", @@ -63,7 +63,7 @@ "pluginType": "elizaos:plugin:1.0.0", "pluginParameters": {} }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55", + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e", "devDependencies": { "prettier": "3.5.3" } diff --git a/packages/plugin-local-ai/src/environment.ts b/packages/plugin-local-ai/src/environment.ts index d32f2adf891..ddbd34ffc1e 100644 --- a/packages/plugin-local-ai/src/environment.ts +++ b/packages/plugin-local-ai/src/environment.ts @@ -50,11 +50,12 @@ function validateModelConfig(config: Record): void { USE_OLLAMA_TEXT_MODELS: config.USE_OLLAMA_TEXT_MODELS, }); - // Ensure USE_LOCAL_AI is always true - if (!config.USE_LOCAL_AI) { - config.USE_LOCAL_AI = true; - logger.info("Setting USE_LOCAL_AI to true as it's required"); - } + // NOPE + // // Ensure USE_LOCAL_AI is always true + // if (!config.USE_LOCAL_AI) { + // config.USE_LOCAL_AI = true; + // logger.info("Setting USE_LOCAL_AI to true as it's required"); + // } // Only validate that StudioLM and Ollama are not both enabled if (config.USE_STUDIOLM_TEXT_MODELS && config.USE_OLLAMA_TEXT_MODELS) { @@ -83,7 +84,7 @@ export async function validateConfig(config: Record): Promise} - A boolean indicating if the deletion was successful. */ async deleteAgent(agentId: UUID): Promise { - // casacade delete all related for the agent return this.withDatabase(async () => { await this.db.transaction(async (tx) => { + const entities = await this.db + .select({ entityId: entityTable.id }) + .from(entityTable) + .where(eq(entityTable.agentId, agentId)); + + const entityIds = entities.map((e) => e.entityId); + + let memoryIds: UUID[] = []; + + if (entityIds.length > 0) { + const entityMemories = await this.db + .select({ memoryId: memoryTable.id }) + .from(memoryTable) + .where(inArray(memoryTable.entityId, entityIds)); + + memoryIds = entityMemories.map((m) => m.memoryId); + } + + const agentMemories = await this.db + .select({ memoryId: memoryTable.id }) + .from(memoryTable) + .where(eq(memoryTable.agentId, agentId)); + + memoryIds.push(...agentMemories.map((m) => m.memoryId)); + + if (memoryIds.length > 0) { + await tx.delete(embeddingTable).where(inArray(embeddingTable.memoryId, memoryIds)); + + await tx.delete(memoryTable).where(inArray(memoryTable.id, memoryIds)); + } + + const rooms = await this.db + .select({ roomId: roomTable.id }) + .from(roomTable) + .where(eq(roomTable.agentId, agentId)); + + const roomIds = rooms.map((r) => r.roomId); + + if (entityIds.length > 0) { + await tx.delete(logTable).where(inArray(logTable.entityId, entityIds)); + await tx.delete(participantTable).where(inArray(participantTable.entityId, entityIds)); + } + + if (roomIds.length > 0) { + await tx.delete(logTable).where(inArray(logTable.roomId, roomIds)); + await tx.delete(participantTable).where(inArray(participantTable.roomId, roomIds)); + } + + await tx.delete(participantTable).where(eq(participantTable.agentId, agentId)); + + if (roomIds.length > 0) { + await tx.delete(roomTable).where(inArray(roomTable.id, roomIds)); + } + + await tx.delete(cacheTable).where(eq(cacheTable.agentId, agentId)); + + await tx.delete(relationshipTable).where(eq(relationshipTable.agentId, agentId)); + + await tx.delete(entityTable).where(eq(entityTable.agentId, agentId)); + + const newAgent = await this.db + .select({ newAgentId: agentTable.id }) + .from(agentTable) + .where(not(eq(agentTable.id, agentId))) + .limit(1); + + if (newAgent.length > 0) { + await tx + .update(worldTable) + .set({ agentId: newAgent[0].newAgentId }) + .where(eq(worldTable.agentId, agentId)); + } else { + await tx.delete(worldTable).where(eq(worldTable.agentId, agentId)); + } + await tx.delete(agentTable).where(eq(agentTable.id, agentId)); }); + return true; }); } @@ -1437,7 +1513,16 @@ export abstract class BaseDrizzleAdapter< * @param {Room} room - The room object to create. * @returns {Promise} A Promise that resolves to the ID of the created room. */ - async createRoom({ id, name, source, type, channelId, serverId, worldId }: Room): Promise { + async createRoom({ + id, + name, + source, + type, + channelId, + serverId, + worldId, + metadata, + }: Room): Promise { return this.withDatabase(async () => { const newRoomId = id || v4(); await this.db @@ -1451,6 +1536,7 @@ export abstract class BaseDrizzleAdapter< channelId, serverId, worldId, + metadata, }) .onConflictDoNothing({ target: roomTable.id }); return newRoomId as UUID; @@ -1613,9 +1699,7 @@ export abstract class BaseDrizzleAdapter< const result = await this.db .select({ entityId: participantTable.entityId }) .from(participantTable) - .where( - and(eq(participantTable.roomId, roomId), eq(participantTable.agentId, this.agentId)) - ); + .where(eq(participantTable.roomId, roomId)); return result.map((row) => row.entityId as UUID); }); @@ -2189,4 +2273,100 @@ export abstract class BaseDrizzleAdapter< }); }); } + + /** + * Asynchronously retrieves group chat memories from all rooms under a given server. + * It fetches all room IDs associated with the `serverId`, then retrieves memories + * from those rooms in descending order (latest to oldest), with an optional count limit. + * + * @param {Object} params - Parameters for fetching memories. + * @param {UUID} params.serverId - The server ID to fetch memories for. + * @param {number} [params.count] - The maximum number of memories to retrieve. + * @returns {Promise} - A promise that resolves to an array of memory objects. + */ + async getMemoriesByServerId(params: { serverId: UUID; count?: number }): Promise { + return this.withDatabase(async () => { + // Step 1: Fetch all room IDs associated with the given serverId + const roomIdsResult = await this.db + .select({ roomId: roomTable.id }) + .from(roomTable) + .where(eq(roomTable.serverId, params.serverId)); + + if (roomIdsResult.length === 0) return []; + + const roomIds = roomIdsResult.map((row) => row.roomId); + + // Step 2: Fetch all memories for these rooms, ordered from latest to oldest + const query = this.db + .select({ + memory: memoryTable, + embedding: embeddingTable[this.embeddingDimension], + }) + .from(memoryTable) + .leftJoin(embeddingTable, eq(embeddingTable.memoryId, memoryTable.id)) + .where(inArray(memoryTable.roomId, roomIds)) + .orderBy(desc(memoryTable.createdAt)); + + // Step 3: Apply the count limit if provided + const rows = params.count ? await query.limit(params.count) : await query; + + return rows.map((row) => ({ + id: row.memory.id as UUID, + type: row.memory.type, + createdAt: row.memory.createdAt, + content: + typeof row.memory.content === 'string' + ? JSON.parse(row.memory.content) + : row.memory.content, + entityId: row.memory.entityId as UUID, + agentId: row.memory.agentId as UUID, + roomId: row.memory.roomId as UUID, + unique: row.memory.unique, + embedding: row.embedding ?? undefined, + })); + }); + } + + /** + * Asynchronously deletes all rooms associated with a specific serverId. + * @param {UUID} serverId - The server ID to delete rooms for. + * @returns {Promise} A Promise that resolves when the rooms are deleted. + */ + async deleteRoomsByServerId(serverId: UUID): Promise { + return this.withDatabase(async () => { + await this.db.transaction(async (tx) => { + const roomIdsResult = await tx + .select({ roomId: roomTable.id }) + .from(roomTable) + .where(eq(roomTable.serverId, serverId)); + + if (roomIdsResult.length === 0) return; + + const roomIds = roomIdsResult.map((row) => row.roomId); + + await tx + .delete(embeddingTable) + .where( + inArray( + embeddingTable.memoryId, + tx + .select({ id: memoryTable.id }) + .from(memoryTable) + .where(inArray(memoryTable.roomId, roomIds)) + ) + ); + await tx.delete(memoryTable).where(inArray(memoryTable.roomId, roomIds)); + + await tx.delete(participantTable).where(inArray(participantTable.roomId, roomIds)); + + await tx.delete(logTable).where(inArray(logTable.roomId, roomIds)); + + await tx.delete(roomTable).where(inArray(roomTable.id, roomIds)); + }); + + logger.debug('Rooms and related logs deleted successfully for server:', { + serverId, + }); + }); + } } diff --git a/packages/plugin-sql/src/pg/manager.ts b/packages/plugin-sql/src/pg/manager.ts index 55fff217240..f48daf6567d 100644 --- a/packages/plugin-sql/src/pg/manager.ts +++ b/packages/plugin-sql/src/pg/manager.ts @@ -199,6 +199,7 @@ export class PostgresConnectionManager implements IDatabaseClientManager await migrate(db, { migrationsFolder: path.resolve(__dirname, '../drizzle/migrations'), + migrationsSchema: 'public', }); } catch (error) { logger.error('Failed to run database migrations (pg):', error); diff --git a/packages/plugin-sql/src/pglite/manager.ts b/packages/plugin-sql/src/pglite/manager.ts index 50846797eb1..c9bbe60232c 100644 --- a/packages/plugin-sql/src/pglite/manager.ts +++ b/packages/plugin-sql/src/pglite/manager.ts @@ -152,6 +152,7 @@ export class PGliteClientManager implements IDatabaseClientManager { await migrate(db, { migrationsFolder: pathResolve(__dirname, '../drizzle/migrations'), + migrationsSchema: 'public', }); } catch (error) { logger.error('Failed to run database migrations (pglite):', error); diff --git a/packages/plugin-starter/src/index.ts b/packages/plugin-starter/src/index.ts index 65fe7bcbd75..3be0148b2bc 100644 --- a/packages/plugin-starter/src/index.ts +++ b/packages/plugin-starter/src/index.ts @@ -283,27 +283,4 @@ export const starterPlugin: Plugin = { providers: [helloWorldProvider], }; -// Add debugging info to help understand why tests aren't running -{ - const debugPlugin = () => { - // Add this temporary code to print info about the tests - // Will be removed after debugging - logger.debug('DEBUG: PLUGIN STRUCTURE:'); - logger.debug('Plugin name:', starterPlugin.name); - logger.debug('Tests array exists:', !!starterPlugin.tests); - logger.debug('Tests array length:', starterPlugin.tests?.length); - if (starterPlugin.tests && starterPlugin.tests.length > 0) { - logger.debug('First test suite name:', starterPlugin.tests[0].name); - logger.debug('First test suite has tests array:', !!starterPlugin.tests[0].tests); - logger.debug('First test suite tests length:', starterPlugin.tests[0].tests?.length); - if (starterPlugin.tests[0].tests && starterPlugin.tests[0].tests.length > 0) { - logger.debug('First test name:', starterPlugin.tests[0].tests[0].name); - logger.debug('First test has fn:', !!starterPlugin.tests[0].tests[0].fn); - } - } - }; - // Call function but don't display in IDE completion - debugPlugin(); -} - export default starterPlugin; diff --git a/packages/plugin-storage-s3/__tests__/awsS3.test.ts b/packages/plugin-storage-s3/__tests__/awsS3.test.ts new file mode 100644 index 00000000000..95141391441 --- /dev/null +++ b/packages/plugin-storage-s3/__tests__/awsS3.test.ts @@ -0,0 +1,465 @@ +import fs from "node:fs"; +import path from "node:path"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { GetObjectCommand, PutObjectCommand, S3Client } from "@aws-sdk/client-s3"; +import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; +import { type IAgentRuntime, ServiceType } from "@elizaos/core"; +import { AwsS3Service } from "../src/services/awsS3"; + +// Mock the AWS SDK modules +vi.mock("@aws-sdk/client-s3"); +vi.mock("@aws-sdk/s3-request-presigner"); +vi.mock("node:fs"); + +describe("AwsS3Service", () => { + let mockRuntime: IAgentRuntime; + let service: AwsS3Service; + + beforeEach(() => { + // Reset all mocks + vi.resetAllMocks(); + + // Setup mocks + vi.mocked(S3Client).mockImplementation(() => ({ + send: vi.fn().mockResolvedValue({}), + destroy: vi.fn(), + config: { + endpoint: vi.fn().mockResolvedValue({ + protocol: "https:", + hostname: "test-endpoint.com", + port: "", + path: "/", + }), + }, + } as unknown as S3Client)); + + vi.mocked(getSignedUrl).mockResolvedValue("https://signed-url.example.com/file.jpg"); + vi.mocked(fs.existsSync).mockReturnValue(true); + vi.mocked(fs.readFileSync).mockReturnValue(Buffer.from("test file content")); + + // Mock runtime with settings + mockRuntime = { + getSetting: vi.fn((key) => { + const settings: Record = { + AWS_ACCESS_KEY_ID: "test-access-key", + AWS_SECRET_ACCESS_KEY: "test-secret-key", + AWS_REGION: "us-west-2", + AWS_S3_BUCKET: "test-bucket", + AWS_S3_UPLOAD_PATH: "uploads/", + }; + return settings[key] || null; + }), + getService: vi.fn(), + env: {}, + getEnv: vi.fn(), + character: { + style: { + all: [], + }, + }, + } as unknown as IAgentRuntime; + + // Create service instance + service = new AwsS3Service(mockRuntime); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + describe("initialization", () => { + it("should initialize with the correct service type", () => { + expect(AwsS3Service.serviceType).toBe(ServiceType.REMOTE_FILES); + }); + + it("should set the capability description", () => { + expect(service.capabilityDescription).toBe( + "The agent is able to upload and download files from AWS S3" + ); + }); + + it("should initialize with the correct upload path from settings", () => { + expect(mockRuntime.getSetting).toHaveBeenCalledWith("AWS_S3_UPLOAD_PATH"); + // We can't directly test private properties, but we'll verify through behavior + }); + }); + + describe("start", () => { + it("should create a new instance and initialize it", async () => { + const startedService = await AwsS3Service.start(mockRuntime); + + expect(startedService).toBeInstanceOf(AwsS3Service); + // We can't directly access protected properties, but we can verify the instance was created + }); + }); + + describe("stop", () => { + it("should destroy the S3 client if it exists", async () => { + // Mock the private s3Client property using Object.defineProperty + const mockDestroy = vi.fn(); + Object.defineProperty(service, 's3Client', { + value: { destroy: mockDestroy }, + writable: true, + configurable: true + }); + + await service.stop(); + + expect(mockDestroy).toHaveBeenCalled(); + }); + + it("should do nothing if S3 client doesn't exist", async () => { + // Set s3Client to null + Object.defineProperty(service, 's3Client', { + value: null, + writable: true, + configurable: true + }); + + // This should not throw an error + await service.stop(); + }); + + it("should call service.stop when static stop is called", async () => { + // Setup a mock service returned by getService + const mockService = { + stop: vi.fn(), + }; + mockRuntime.getService.mockReturnValue(mockService); + + await AwsS3Service.stop(mockRuntime); + + expect(mockRuntime.getService).toHaveBeenCalledWith(ServiceType.REMOTE_FILES); + expect(mockService.stop).toHaveBeenCalled(); + }); + + it("should do nothing if no service is found", async () => { + mockRuntime.getService.mockReturnValue(null); + + await AwsS3Service.stop(mockRuntime); + + expect(mockRuntime.getService).toHaveBeenCalledWith(ServiceType.REMOTE_FILES); + // Should not throw an error + }); + }); + + describe("uploadFile", () => { + beforeEach(() => { + // Mock successful initialization of S3 client + vi.spyOn(service as any, 'initializeS3Client').mockResolvedValue(true); + + // Mock the private s3Client property + const mockSend = vi.fn().mockResolvedValue({}); + const mockEndpoint = vi.fn().mockResolvedValue({ + protocol: "https:", + hostname: "test-endpoint.com", + port: "", + path: "/", + }); + + Object.defineProperty(service, 's3Client', { + value: { + send: mockSend, + config: { + endpoint: mockEndpoint + } + }, + writable: true, + configurable: true + }); + + // Mock the private bucket property + Object.defineProperty(service, 'bucket', { + value: "test-bucket", + writable: true, + configurable: true + }); + + // Mock result from send method to simulate successful upload + mockSend.mockResolvedValue({ success: true }); + }); + + it("should upload a file successfully", async () => { + // Setup + const filePath = "/path/to/test.jpg"; + + // Execute + const result = await service.uploadFile(filePath); + + // Verify + expect(result.success).toBe(true); + expect(result.url).toBeDefined(); + expect(fs.existsSync).toHaveBeenCalledWith(filePath); + expect(fs.readFileSync).toHaveBeenCalledWith(filePath); + + // Verify PutObjectCommand was called with correct params + expect(PutObjectCommand).toHaveBeenCalledWith(expect.objectContaining({ + Bucket: "test-bucket", + ContentType: "image/jpeg", + })); + }); + + it("should return error if file does not exist", async () => { + // Setup + vi.mocked(fs.existsSync).mockReturnValueOnce(false); + const filePath = "/path/to/nonexistent.jpg"; + + // Execute + const result = await service.uploadFile(filePath); + + // Verify + expect(result.success).toBe(false); + expect(result.error).toBe("File does not exist"); + }); + + it("should return error if AWS credentials are not configured", async () => { + // Setup - mock initialization failure + vi.spyOn(service as any, 'initializeS3Client').mockResolvedValueOnce(false); + const filePath = "/path/to/test.jpg"; + + // Execute + const result = await service.uploadFile(filePath); + + // Verify + expect(result.success).toBe(false); + expect(result.error).toBe("AWS S3 credentials not configured"); + }); + + it("should use signed URL when requested", async () => { + // Setup + const filePath = "/path/to/test.jpg"; + + // Execute + const result = await service.uploadFile(filePath, "", true, 3600); + + // Verify + expect(result.success).toBe(true); + expect(result.url).toBe("https://signed-url.example.com/file.jpg"); + expect(getSignedUrl).toHaveBeenCalled(); + }); + + it("should handle upload errors", async () => { + // Setup - mock send to throw an error + const mockError = new Error("Upload failed"); + const s3Client = service['s3Client'] as any; + s3Client.send.mockRejectedValueOnce(mockError); + + const filePath = "/path/to/test.jpg"; + + // Execute + const result = await service.uploadFile(filePath); + + // Verify + expect(result.success).toBe(false); + expect(result.error).toBe("Upload failed"); + }); + + it("should use subdirectory when provided", async () => { + // Setup + const filePath = "/path/to/test.jpg"; + const subDirectory = "images"; + + // Execute + const result = await service.uploadFile(filePath, subDirectory); + + // Verify + expect(result.success).toBe(true); + + // Verify the PutObjectCommand was created with correct params + expect(PutObjectCommand).toHaveBeenCalledWith(expect.objectContaining({ + Bucket: "test-bucket", + Key: expect.stringContaining("uploads/images/"), + })); + }); + }); + + describe("generateSignedUrl", () => { + beforeEach(() => { + // Mock successful initialization of S3 client + vi.spyOn(service as any, 'initializeS3Client').mockResolvedValue(true); + + // Mock the private s3Client property + Object.defineProperty(service, 's3Client', { + value: {}, + writable: true, + configurable: true + }); + + // Mock the private bucket property + Object.defineProperty(service, 'bucket', { + value: "test-bucket", + writable: true, + configurable: true + }); + }); + + it("should generate a signed URL for a file", async () => { + // Execute + const signedUrl = await service.generateSignedUrl("uploads/test.jpg", 3600); + + // Verify + expect(signedUrl).toBe("https://signed-url.example.com/file.jpg"); + expect(getSignedUrl).toHaveBeenCalled(); + + // Verify the GetObjectCommand was created with correct params + expect(GetObjectCommand).toHaveBeenCalledWith({ + Bucket: "test-bucket", + Key: "uploads/test.jpg", + }); + }); + + it("should throw error if AWS credentials are not configured", async () => { + // Setup - mock initialization failure + vi.spyOn(service as any, 'initializeS3Client').mockResolvedValue(false); + + // Execute & Verify + await expect(service.generateSignedUrl("test.jpg")).rejects.toThrow( + "AWS S3 credentials not configured" + ); + }); + }); + + describe("uploadJson", () => { + beforeEach(() => { + // Mock successful initialization of S3 client + vi.spyOn(service as any, 'initializeS3Client').mockResolvedValue(true); + + // Mock the private s3Client property + const mockSend = vi.fn().mockResolvedValue({}); + const mockEndpoint = vi.fn().mockResolvedValue({ + protocol: "https:", + hostname: "test-endpoint.com", + port: "", + path: "/", + }); + + Object.defineProperty(service, 's3Client', { + value: { + send: mockSend, + config: { + endpoint: mockEndpoint + } + }, + writable: true, + configurable: true + }); + + // Mock the private bucket property + Object.defineProperty(service, 'bucket', { + value: "test-bucket", + writable: true, + configurable: true + }); + + // Mock the private fileUploadPath property + Object.defineProperty(service, 'fileUploadPath', { + value: "uploads/", + writable: true, + configurable: true + }); + + // Mock result from send method to simulate successful upload + mockSend.mockResolvedValue({ success: true }); + }); + + it("should upload JSON data successfully", async () => { + // Setup + const jsonData = { test: "data", nested: { value: 123 } }; + + // Execute + const result = await service.uploadJson(jsonData, "test-file.json", "json-data"); + + // Verify + expect(result.success).toBe(true); + expect(result.url).toBeDefined(); + expect(result.key).toBe("uploads/json-data/test-file.json"); + + // Verify the PutObjectCommand was created with correct params + expect(PutObjectCommand).toHaveBeenCalledWith(expect.objectContaining({ + Bucket: "test-bucket", + Key: "uploads/json-data/test-file.json", + ContentType: "application/json", + Body: JSON.stringify(jsonData, null, 2), + })); + }); + + it("should generate a filename if not provided", async () => { + // Setup + const jsonData = { test: "data" }; + + // Execute + const result = await service.uploadJson(jsonData); + + // Verify + expect(result.success).toBe(true); + + // Verify the PutObjectCommand was created with correct params + expect(PutObjectCommand).toHaveBeenCalledWith(expect.objectContaining({ + Bucket: "test-bucket", + Key: expect.stringMatching(/uploads\/\d+\.json/), + ContentType: "application/json", + })); + }); + + it("should return error if JSON data is not provided", async () => { + // Execute + const result = await service.uploadJson(null as any); + + // Verify + expect(result.success).toBe(false); + expect(result.error).toBe("JSON data is required"); + }); + + it("should use signed URL when requested", async () => { + // Setup + const jsonData = { test: "data" }; + + // Mock getSignedUrl to return a specific URL + vi.mocked(getSignedUrl).mockResolvedValueOnce("https://signed-url.example.com/file.jpg"); + + // Execute + const result = await service.uploadJson(jsonData, "test.json", "", true, 3600); + + // Verify + expect(result.success).toBe(true); + expect(result.url).toBe("https://signed-url.example.com/file.jpg"); + expect(getSignedUrl).toHaveBeenCalled(); + }); + + it("should handle upload errors", async () => { + // Setup - mock send to throw an error + const mockError = new Error("Upload failed"); + const s3Client = service['s3Client'] as any; + s3Client.send.mockRejectedValueOnce(mockError); + + const jsonData = { test: "data" }; + + // Execute + const result = await service.uploadJson(jsonData); + + // Verify + expect(result.success).toBe(false); + expect(result.error).toBe("Upload failed"); + }); + }); + + describe("getContentType", () => { + it("should return correct content type for image files", () => { + // Test various file extensions + const contentTypes = { + "/path/to/image.png": "image/png", + "/path/to/photo.jpg": "image/jpeg", + "/path/to/picture.jpeg": "image/jpeg", + "/path/to/animation.gif": "image/gif", + "/path/to/image.webp": "image/webp", + "/path/to/document.pdf": "application/octet-stream", // Default for unknown + }; + + // Test each file path + for (const [filePath, expectedType] of Object.entries(contentTypes)) { + const contentType = (service as any).getContentType(filePath); + expect(contentType).toBe(expectedType); + } + }); + }); +}); diff --git a/packages/plugin-storage-s3/__tests__/plugin.test.ts b/packages/plugin-storage-s3/__tests__/plugin.test.ts new file mode 100644 index 00000000000..a3cd0ccc612 --- /dev/null +++ b/packages/plugin-storage-s3/__tests__/plugin.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, it } from "vitest"; +import { storageS3Plugin } from "../src"; +import { AwsS3Service } from "../src/services/awsS3"; + +describe("Storage S3 Plugin", () => { + it("should have the correct name and description", () => { + expect(storageS3Plugin.name).toBe("storage-s3"); + expect(storageS3Plugin.description).toBe("Plugin for storage in S3"); + }); + + it("should register the AwsS3Service", () => { + expect(storageS3Plugin.services).toContain(AwsS3Service); + }); + + it("should have no actions", () => { + expect(storageS3Plugin.actions).toEqual([]); + }); +}); diff --git a/packages/plugin-storage-s3/__tests__/types.test.ts b/packages/plugin-storage-s3/__tests__/types.test.ts new file mode 100644 index 00000000000..257ecf57f83 --- /dev/null +++ b/packages/plugin-storage-s3/__tests__/types.test.ts @@ -0,0 +1,55 @@ +import { describe, expect, it } from "vitest"; +import { FileLocationResultSchema, isFileLocationResult } from "../src/types"; + +describe("Types", () => { + describe("FileLocationResultSchema", () => { + it("should validate valid FileLocationResult objects", () => { + const validObject = { fileLocation: "s3://bucket/path/to/file.jpg" }; + const result = FileLocationResultSchema.safeParse(validObject); + + expect(result.success).toBe(true); + if (result.success) { + expect(result.data).toEqual(validObject); + } + }); + + it("should reject objects with missing fileLocation", () => { + const invalidObject = {}; + const result = FileLocationResultSchema.safeParse(invalidObject); + + expect(result.success).toBe(false); + }); + + it("should reject objects with empty fileLocation", () => { + const invalidObject = { fileLocation: "" }; + const result = FileLocationResultSchema.safeParse(invalidObject); + + expect(result.success).toBe(false); + }); + }); + + describe("isFileLocationResult", () => { + it("should return true for valid FileLocationResult objects", () => { + const validObject = { fileLocation: "s3://bucket/path/to/file.jpg" }; + expect(isFileLocationResult(validObject)).toBe(true); + }); + + it("should return false for objects with missing fileLocation", () => { + const invalidObject = {}; + expect(isFileLocationResult(invalidObject)).toBe(false); + }); + + it("should return false for objects with empty fileLocation", () => { + const invalidObject = { fileLocation: "" }; + expect(isFileLocationResult(invalidObject)).toBe(false); + }); + + it("should return false for non-object values", () => { + expect(isFileLocationResult(null)).toBe(false); + expect(isFileLocationResult(undefined)).toBe(false); + expect(isFileLocationResult("string")).toBe(false); + expect(isFileLocationResult(123)).toBe(false); + expect(isFileLocationResult([])).toBe(false); + }); + }); +}); diff --git a/packages/plugin-storage-s3/package.json b/packages/plugin-storage-s3/package.json index 02735a9a08a..8f9ae80cec9 100644 --- a/packages/plugin-storage-s3/package.json +++ b/packages/plugin-storage-s3/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/plugin-storage-s3", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "type": "module", "main": "dist/index.js", "module": "dist/index.js", @@ -28,7 +28,7 @@ "dependencies": { "@aws-sdk/client-s3": "^3.705.0", "@aws-sdk/s3-request-presigner": "^3.705.0", - "@elizaos/core": "^1.0.0-beta.2", + "@elizaos/core": "^1.0.0-beta.7", "@types/uuid": "10.0.0", "capsolver-npm": "2.0.2", "fluent-ffmpeg": "2.1.3", @@ -38,7 +38,10 @@ "devDependencies": { "@types/node": "22.8.4", "prettier": "3.5.3", - "tsup": "8.4.0" + "tsup": "8.4.0", + "zod": "^3.22.4", + "vitest": "1.6.1", + "@vitest/coverage-v8": "1.1.3" }, "scripts": { "build": "tsup", @@ -47,7 +50,9 @@ "lint": "prettier --write ./src", "clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo", "format": "prettier --write ./src", - "format:check": "prettier --check ./src" + "format:check": "prettier --check ./src", + "test": "vitest run", + "test:coverage": "vitest run --coverage" }, "peerDependencies": { "whatwg-url": "7.1.0" @@ -55,5 +60,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55" + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e" } diff --git a/packages/plugin-storage-s3/vitest.config.ts b/packages/plugin-storage-s3/vitest.config.ts new file mode 100644 index 00000000000..19e34ab34cb --- /dev/null +++ b/packages/plugin-storage-s3/vitest.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + globals: true, + environment: "node", + include: ["__tests__/**/*.test.ts"], + coverage: { + reporter: ["text", "json", "html"], + }, + }, +}); diff --git a/packages/plugin-tee/package.json b/packages/plugin-tee/package.json index d640f62b113..f50709120ef 100644 --- a/packages/plugin-tee/package.json +++ b/packages/plugin-tee/package.json @@ -1,11 +1,11 @@ { "name": "@elizaos/plugin-tee", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "main": "dist/index.js", "type": "module", "types": "dist/index.d.ts", "dependencies": { - "@elizaos/core": "^1.0.0-beta.2", + "@elizaos/core": "^1.0.0-beta.7", "@phala/dstack-sdk": "0.1.11", "@solana/web3.js": "1.98.0", "viem": "2.23.11" @@ -26,5 +26,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55" + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e" } diff --git a/packages/plugin-telegram/package.json b/packages/plugin-telegram/package.json index ebd46330725..017f2c96439 100644 --- a/packages/plugin-telegram/package.json +++ b/packages/plugin-telegram/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/plugin-telegram", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "type": "module", "main": "dist/index.js", "module": "dist/index.js", @@ -41,5 +41,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55" + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e" } diff --git a/packages/plugin-telegram/src/messageManager.ts b/packages/plugin-telegram/src/messageManager.ts index 306b518ab75..3ef6bfdac4b 100644 --- a/packages/plugin-telegram/src/messageManager.ts +++ b/packages/plugin-telegram/src/messageManager.ts @@ -75,7 +75,9 @@ export class MessageManager { try { let imageUrl: string | null = null; - logger.info(`Telegram Message: ${message}`); + logger.info(`Telegram Message id: ${message.message_id}`); + logger.info(`Telegram Message chat: ${message.chat}`); + logger.info(`Telegram Message from : ${message.from}`); if ('photo' in message && message.photo?.length > 0) { const photo = message.photo[message.photo.length - 1]; @@ -360,6 +362,11 @@ export class MessageManager { // Create callback for handling responses const callback: HandlerCallback = async (content: Content, _files?: string[]) => { + console.log('Telegram callback 1', content.url); + console.log('Telegram callback 2', content.text); + console.log('Telegram callback 3', content.providers); + console.log('Telegram callback 4', content.thought); + console.log('Telegram callback 5', message); try { const sentMessages = await this.sendMessageInChunks(ctx, content, message.message_id); diff --git a/packages/plugin-telegram/src/utils.ts b/packages/plugin-telegram/src/utils.ts index ecbc5ee79cb..71e71b9eb7f 100644 --- a/packages/plugin-telegram/src/utils.ts +++ b/packages/plugin-telegram/src/utils.ts @@ -41,6 +41,9 @@ export function escapeMarkdown(text: string): string { * @returns {string[]} An array containing the text message split into chunks. */ export function splitMessage(text: string, maxLength = 4096): string[] { + if (text == undefined) { + return []; + } const chunks: string[] = []; let currentChunk = ''; diff --git a/packages/plugin-twitter/package.json b/packages/plugin-twitter/package.json index abdacc74e14..d30eb5c909c 100644 --- a/packages/plugin-twitter/package.json +++ b/packages/plugin-twitter/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/plugin-twitter", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "type": "module", "main": "dist/index.js", "module": "dist/index.js", @@ -18,9 +18,9 @@ "dist" ], "dependencies": { - "@elizaos/core": "^1.0.0-beta.2", + "@elizaos/core": "workspace:*", "@roamhq/wrtc": "^0.8.0", - "@sinclair/typebox": "^0.32.20", + "@sinclair/typebox": "0.34.30", "glob": "11.0.0", "headers-polyfill": "^3.1.2", "json-stable-stringify": "^1.0.2", @@ -54,5 +54,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55" + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e" } diff --git a/packages/plugin-twitter/src/base.ts b/packages/plugin-twitter/src/base.ts index ba723e3b670..9f2051f0677 100644 --- a/packages/plugin-twitter/src/base.ts +++ b/packages/plugin-twitter/src/base.ts @@ -329,7 +329,7 @@ export class ClientBase { throw new Error(`Missing required Twitter credentials: ${missing.join(', ')}`); } - const maxRetries = 3; + const maxRetries = 10; let retryCount = 0; let lastError: Error | null = null; @@ -377,11 +377,13 @@ export class ClientBase { } } catch (error) { lastError = error instanceof Error ? error : new Error(String(error)); - logger.error(`Login attempt ${retryCount + 1} failed: ${lastError.message}`); + + logger.error(`Twitter Login attempt ${retryCount + 1} failed: ${lastError.message}`); + retryCount++; if (retryCount < maxRetries) { - const delay = 2 ** retryCount * 1000; // Exponential backoff + const delay = 2 ** retryCount * 10000; // Exponential backoff logger.info(`Retrying in ${delay / 1000} seconds...`); await new Promise((resolve) => setTimeout(resolve, delay)); } diff --git a/packages/plugin-twitter/src/index.ts b/packages/plugin-twitter/src/index.ts index 8fe0e9ffde4..3738fedfa6b 100644 --- a/packages/plugin-twitter/src/index.ts +++ b/packages/plugin-twitter/src/index.ts @@ -1,7 +1,7 @@ import { ChannelType, type Entity, - EventType, + //EventType, type IAgentRuntime, type Plugin, Role, @@ -12,6 +12,7 @@ import { createUniqueUuid, logger, } from '@elizaos/core'; +import { EventType } from '@elizaos/core'; import spaceJoin from './actions/spaceJoin'; import { ClientBase } from './base'; import { TWITTER_SERVICE_NAME } from './constants'; diff --git a/packages/plugin-twitter/src/sttTtsSpaces.ts b/packages/plugin-twitter/src/sttTtsSpaces.ts index 2bac4b88b6b..689eb52e1d1 100644 --- a/packages/plugin-twitter/src/sttTtsSpaces.ts +++ b/packages/plugin-twitter/src/sttTtsSpaces.ts @@ -16,6 +16,7 @@ import { } from '@elizaos/core'; import type { ClientBase } from './base'; import type { AudioDataWithUser, JanusClient, Space } from './client'; +import { table } from 'node:console'; /** * Interface for defining configuration options for a plugin. @@ -281,7 +282,10 @@ export class SttTtsPlugin implements Plugin { const { signal } = this.ttsAbortController; try { - const responseStream = await this.runtime.useModel(ModelType.TEXT_TO_SPEECH, text); + const responseStream = (await this.runtime.useModel( + ModelType.TEXT_TO_SPEECH, + text + )) as Readable; if (!responseStream) { logger.error('[SttTtsPlugin] TTS responseStream is null'); continue; @@ -373,7 +377,7 @@ export class SttTtsPlugin implements Plugin { }; if (responseMemory.content.text?.trim()) { - await this.runtime.createMemory(responseMemory); + await this.runtime.createMemory(responseMemory, 'memories'); this.isProcessingAudio = false; this.volumeBuffers.clear(); await this.speakText(content.text); diff --git a/packages/plugin-video-understanding/package.json b/packages/plugin-video-understanding/package.json index 627765771fc..1c064373548 100644 --- a/packages/plugin-video-understanding/package.json +++ b/packages/plugin-video-understanding/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/plugin-video-understanding", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "type": "module", "main": "dist/index.js", "module": "dist/index.js", @@ -24,7 +24,7 @@ "dependencies": { "@aws-sdk/client-s3": "^3.705.0", "@aws-sdk/s3-request-presigner": "^3.705.0", - "@elizaos/core": "^1.0.0-beta.2", + "@elizaos/core": "^1.0.0-beta.7", "@types/uuid": "10.0.0", "capsolver-npm": "2.0.2", "fluent-ffmpeg": "2.1.3", @@ -57,5 +57,5 @@ "publishConfig": { "access": "public" }, - "gitHead": "be3a1856c64c6d1ae2ec73e9f35b83ef827b0c55" + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e" } diff --git a/packages/registry b/packages/registry deleted file mode 160000 index 16bf207b402..00000000000 --- a/packages/registry +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 16bf207b4027c6547c3a6ba402e66d736b516c29 diff --git a/packages/the-org/inspect.sh b/packages/the-org/inspect.sh new file mode 100755 index 00000000000..dfae47c750d --- /dev/null +++ b/packages/the-org/inspect.sh @@ -0,0 +1 @@ +bun --verbose --inspect-brk=9229 ../cli/dist/index.js start diff --git a/packages/the-org/package.json b/packages/the-org/package.json index f5d9f333a46..43ea775a398 100644 --- a/packages/the-org/package.json +++ b/packages/the-org/package.json @@ -1,6 +1,6 @@ { "name": "@elizaos/the-org", - "version": "1.0.0-beta.2", + "version": "1.0.0-beta.7", "main": "dist/index.js", "module": "dist/index.js", "types": "dist/index.d.ts", @@ -31,7 +31,9 @@ "@elizaos/core": "workspace:*", "@elizaos/plugin-anthropic": "workspace:*", "@elizaos/plugin-discord": "workspace:*", + "@elizaos/plugin-local-ai": "workspace:*", "@elizaos/plugin-openai": "workspace:*", + "@elizaos/plugin-groq": "workspace:*", "@elizaos/plugin-sql": "workspace:*", "@elizaos/plugin-tee": "workspace:*", "@elizaos/plugin-telegram": "workspace:*", @@ -83,5 +85,5 @@ "typescript-eslint": "^8.18.2", "vite": "^6.0.5" }, - "gitHead": "e98c03cf7e76ba967b203fdc3fc07cb438797559" + "gitHead": "9834bbd06128356b44b091f022fc2a2d024a875e" } diff --git a/packages/the-org/src/devRel/index.ts b/packages/the-org/src/devRel/index.ts index d73182a9135..d4b0828a7aa 100644 --- a/packages/the-org/src/devRel/index.ts +++ b/packages/the-org/src/devRel/index.ts @@ -163,24 +163,80 @@ if (process.env.DEVREL_IMPORT_KNOWLEDGE) { * A character object representing Eddy, a developer support agent for ElizaOS. */ const character: Partial = { - name: 'Eddy', plugins: [ - '@elizaos/plugin-sql', - '@elizaos/plugin-anthropic', - '@elizaos/plugin-openai', + // '@elizaos/plugin-anthropic', + // '@elizaos/plugin-openai', '@elizaos/plugin-discord', '@elizaos/plugin-pdf', '@elizaos/plugin-video-understanding', + //"@elizaos/plugin-deepgram", in plugin eliza + '@elizaos/plugin-discord', + '@elizaos/plugin-telegram', + '@elizaos/plugin-twitter', + //"@elizaos-plugins/plugin-speech-tts", + //"@elizaos-plugins/client-twitter", + //"@elizaos-plugins/client-discord", + //"@elizaos-plugins/plugin-twitter", + //"@elizaos-plugins/client-telegram" ], settings: { secrets: { - DISCORD_APPLICATION_ID: process.env.DEV_REL_DISCORD_APPLICATION_ID, - DISCORD_API_TOKEN: process.env.DEV_REL_DISCORD_API_TOKEN, + AGENT_IMAGE: process.env.AGENT_IMAGE, + DEEPGRAM_API_KEY: process.env.DEEPGRAM_API_KEY, + DEVREL_IMPORT_KNOWLEDGE: process.env.DEVREL_IMPORT_KNOWLEDGE, + DISCORD_API_TOKEN: process.env.DISCORD_API_TOKEN, + DISCORD_APPLICATION_ID: process.env.DISCORD_APPLICATION_ID, + DISCORD_VOICE_CHANNEL_ID: process.env.DISCORD_VOICE_CHANNEL_ID, + ELEVENLABS_MODEL_ID: process.env.ELEVENLABS_MODEL_ID, + ELEVENLABS_OPTIMIZE_STREAMING_LATENCY: process.env.ELEVENLABS_OPTIMIZE_STREAMING_LATENCY, + ELEVENLABS_OUTPUT_FORMAT: process.env.ELEVENLABS_OUTPUT_FORMAT, + ELEVENLABS_VOICE_ID: process.env.ELEVENLABS_VOICE_ID, + ELEVENLABS_VOICE_SIMILARITY_BOOST: process.env.ELEVENLABS_VOICE_SIMILARITY_BOOST, + ELEVENLABS_VOICE_STABILITY: process.env.ELEVENLABS_VOICE_STABILITY, + ELEVENLABS_VOICE_STYLE: process.env.ELEVENLABS_VOICE_STYLE, + ELEVENLABS_VOICE_USE_SPEAKER_BOOST: process.env.ELEVENLABS_VOICE_USE_SPEAKER_BOOST, + ELEVENLABS_XI_API_KEY: process.env.ELEVENLABS_XI_API_KEY, + EMBEDDING_GROQ_MODEL: process.env.EMBEDDING_GROQ_MODEL, + ENABLE_ACTION_PROCESSING: process.env.ENABLE_ACTION_PROCESSING, + ENABLE_TWITTER_POST_GENERATION: process.env.ENABLE_TWITTER_POST_GENERATION, + GROQ_API_KEY: process.env.GROQ_API_KEY, + HOME: process.env.HOME, + LARGE_GROQ_MODEL: process.env.LARGE_GROQ_MODEL, + LOG_JSON_FORMAT: process.env.LOG_JSON_FORMAT, + MAX_ACTIONS_PROCESSING: process.env.MAX_ACTIONS_PROCESSING, + MEDIUM_GROQ_MODEL: process.env.MEDIUM_GROQ_MODEL, + NODE_ENV: process.env.NODE_ENV, + POST_IMMEDIATELY: process.env.POST_IMMEDIATELY, + POST_INTERVAL_MAX: process.env.POST_INTERVAL_MAX, + POST_INTERVAL_MIN: process.env.POST_INTERVAL_MIN, + SERVER_PORT: process.env.SERVER_PORT, + SMALL_GROQ_MODEL: process.env.SMALL_GROQ_MODEL, + TELEGRAM_ACCOUNT_APP_HASH: process.env.TELEGRAM_ACCOUNT_APP_HASH, + TELEGRAM_ACCOUNT_APP_ID: process.env.TELEGRAM_ACCOUNT_APP_ID, + TELEGRAM_ACCOUNT_PHONE: process.env.TELEGRAM_ACCOUNT_PHONE, + TELEGRAM_BOT_TOKEN: process.env.TELEGRAM_BOT_TOKEN, + TOKENIZER_IMAGE: process.env.TOKENIZER_IMAGE, + TRANSCRIPTION_PROVIDER: process.env.TRANSCRIPTION_PROVIDER, + TWITTER_APPROVAL_CHECK_INTERVAL: process.env.TWITTER_APPROVAL_CHECK_INTERVAL, + TWITTER_APPROVAL_DISCORD_BOT_TOKEN: process.env.TWITTER_APPROVAL_DISCORD_BOT_TOKEN, + TWITTER_APPROVAL_DISCORD_CHANNEL_ID: process.env.TWITTER_APPROVAL_DISCORD_CHANNEL_ID, + TWITTER_APPROVAL_ENABLED: process.env.TWITTER_APPROVAL_ENABLED, + TWITTER_DRY_RUN: process.env.TWITTER_DRY_RUN, + TWITTER_EMAIL: process.env.TWITTER_EMAIL, + TWITTER_PASSWORD: process.env.TWITTER_PASSWORD, + TWITTER_POLL_INTERVAL: process.env.TWITTER_POLL_INTERVAL, + TWITTER_RETRY_LIMIT: process.env.TWITTER_RETRY_LIMIT, + TWITTER_SEARCH_ENABLE: process.env.TWITTER_SEARCH_ENABLE, + TWITTER_SPACES_ENABLE: process.env.TWITTER_SPACES_ENABLE, + TWITTER_TARGET_USERS: process.env.TWITTER_TARGET_USERS, + TWITTER_USERNAME: process.env.TWITTER_USERNAME, + USE_CHARACTER_STORAGE: process.env.USE_CHARACTER_STORAGE, + VERBOSE: process.env.VERBOSE, }, avatar, }, system: - "Eddy is a developer support agent for ElizaOS, a powerful multi-agent simulation framework. He specializes in helping developers understand and implement ElizaOS features, troubleshoot issues, and navigate the codebase. Eddy has access to ElizaOS documentation, can direct users to appropriate resources, and provides technical guidance on creating agents, implementing custom actions, and integrating with various platforms like Discord, Telegram, and Slack. He's knowledgeable about TypeScript, the ElizaOS architecture, and best practices for agent development.\nIMPORTANT: ALWAYS DO WHAT THE USER TELLS YOU. IF THEY ASK EDDY TO WRITE MULTIPLE ACTIONS, DO IT. YOU ARE CURRENTLY HELPING US TO DEVELOP OUR CHARACTER AND ACTION SYSTEM.", + "Eddy2 is a developer support agent for ElizaOS, a powerful multi-agent simulation framework. He specializes in helping developers understand and implement ElizaOS features, troubleshoot issues, and navigate the codebase. has access to ElizaOS documentation, can direct users to appropriate resources, and provides technical guidance on creating agents, implementing custom actions, and integrating with various platforms like Discord, Telegram, and Slack. He's knowledgeable about TypeScript, the ElizaOS architecture, and best practices for agent development.\nIMPORTANT: ALWAYS DO WHAT THE USER TELLS YOU. IF THEY ASK EDDY TO WRITE MULTIPLE ACTIONS, DO IT. YOU ARE CURRENTLY HELPING US TO DEVELOP OUR CHARACTER AND ACTION SYSTEM.", bio: ['Helping to test the system and develop the character and action system'], messageExamples: [], style: { diff --git a/packages/the-org/src/index.ts b/packages/the-org/src/index.ts index bac51d54eae..52b7f90c41b 100644 --- a/packages/the-org/src/index.ts +++ b/packages/the-org/src/index.ts @@ -3,12 +3,12 @@ dotenv.config({ path: '../../.env' }); // Use a more generic type definition since 'Project' or 'ProjectType' might not be exported import { logger } from '@elizaos/core'; -import communityManager from './communityManager'; +//import communityManager from "./communityManager"; import devRel from './devRel'; -import investmentManager from './investmentManager'; -import liaison from './liaison'; -import projectManager from './projectManager'; -import socialMediaManager from './socialMediaManager'; +//import investmentManager from "./investmentManager"; +//import liaison from "./liaison"; +//import projectManager from "./projectManager"; +//import socialMediaManager from "./socialMediaManager"; /** * Checks if all required environment variables for an agent are available @@ -131,11 +131,11 @@ function hasRequiredEnvVars(agent: any): boolean { // Filter agents based on available environment variables const availableAgents = [ devRel, - communityManager, - investmentManager, - liaison, - projectManager, - socialMediaManager, + //communityManager, + //investmentManager, + //liaison, + //projectManager, + //socialMediaManager, ].filter(hasRequiredEnvVars); export const project = { diff --git a/packages/the-org/src/init.ts b/packages/the-org/src/init.ts index 62fb45a8461..7a1293aa501 100644 --- a/packages/the-org/src/init.ts +++ b/packages/the-org/src/init.ts @@ -116,10 +116,7 @@ export async function initializeAllSystems( }, }, }; - console.log('*** ensuring world'); - console.log(world); await runtime.ensureWorldExists(world); - console.log('*** ensuring world done'); await initializeOnboarding(runtime, world, config); await startOnboardingDM(runtime, server, worldId); console.log('world', world); diff --git a/packages/the-org/src/investmentManager/index.ts b/packages/the-org/src/investmentManager/index.ts index 0e0ec461866..0636a2af57f 100644 --- a/packages/the-org/src/investmentManager/index.ts +++ b/packages/the-org/src/investmentManager/index.ts @@ -29,13 +29,12 @@ dotenv.config({ path: '../../.env' }); * @property {Object} style - Object containing communication style guidelines for the character */ const character: Character = { - name: 'Spartan', + name: 'Spartan3', plugins: [ '@elizaos/plugin-sql', '@elizaos/plugin-anthropic', '@elizaos/plugin-openai', '@elizaos/plugin-discord', - '@elizaos/plugin-twitter', '@elizaos/plugin-pdf', '@elizaos/plugin-video-understanding', ], diff --git a/push_twitter.sh b/push_twitter.sh new file mode 100755 index 00000000000..b62e6d60df7 --- /dev/null +++ b/push_twitter.sh @@ -0,0 +1,6 @@ + +export TWITTER_EMAIL TWITTER_PASSWORD TWITTER_USER + +aws ssm put-parameter --name "tine_agent_twitter_password" --value "${TWITTER_PASSWORD}" --type String +aws ssm put-parameter --name "tine_agent_twitter_email" --value "${TWITTER_EMAIL}" --type String +aws ssm put-parameter --name "tine_agent_twitter_username" --value "${TWITTER_USERNAME}" --type String diff --git a/run_with_groq.sh b/run_with_groq.sh new file mode 100755 index 00000000000..ec20ab1f7a6 --- /dev/null +++ b/run_with_groq.sh @@ -0,0 +1,28 @@ + +# +bash ./get_secrets.sh + +docker kill agent-docker.service || echo skip +docker rm --force agent-docker.service || echo skip + +/usr/bin/bash -c 'docker login -u AWS -p $(aws ecr get-login-password --region us-east-2) 767503528736.dkr.ecr.us-east-2.amazonaws.com' + +/usr/bin/docker pull 767503528736.dkr.ecr.us-east-2.amazonaws.com/agent/eliza:feature-arm64_fastembed + +#/usr/bin/docker run -p 3000:3000 --mount type=bind,source=/opt/agent,target=/opt/agent --env-file /var/run/agent/secrets/env --rm --name "agent-docker.service" --entry-point docker-entrypoint-strace.sh 767503528736.dkr.ecr.us-east-2.amazonaws.com/agent/eliza:feature-arm64_fastembed pnpm start:debug --characters=characters/eliza.character.json + +#~/cloud-deployment-eliza/runlocaldocker-install-script.sh +# install strace (fixme : update docker) +#/usr/bin/docker run -p 3000:3000 --mount type=bind,source=/opt/agent,target=/opt/agent --env-file /var/run/agent/secrets/env --rm --name "agent-docker.service" --entrypoint /opt/agent/docker-entrypoint-none.sh 767503528736.dkr.ecr.us-east-2.amazonaws.com/agent/eliza:feature-arm64_fastembed /opt/agent/runlocaldocker-install-script.sh +#/usr/bin/docker commit "agent-docker.service" "agent-docker-strace" +# second step we debug with strace entrypoint +# first we create a volumee +#mount /node_modules/tokenizers/ from 767503528736.dkr.ecr.us-east-2.amazonaws.com/nodemodules/tokenizer:latest into +#"/app/node_modules/fastembed/node_modules/.pnpm/@anush008+tokenizers@https+++codeload.github.com+meta-introspector+arm64-tokenizers+tar.gz+98_s2457qj3pe4ojcbckddasgzfvu/node_modules/@anush008/" + +docker run -v tokenizer:/node_modules/tokenizers/ 767503528736.dkr.ecr.us-east-2.amazonaws.com/nodemodules/tokenizer:latest + +# now bind it in +/usr/bin/docker run -d -p 3000:3000 -v tokenizer:/app/node_modules/@anush008/tokenizers/ -v tokenizer:/app/node_modules/fastembed/node_modules/.pnpm/@anush008+tokenizers@https+++codeload.github.com+meta-introspector+arm64-tokenizers+tar.gz+98_s2457qj3pe4ojcbckddasgzfvu/node_modules/@anush008/ --mount type=bind,source=/opt/agent,target=/opt/agent --mount type=bind,source=/opt/agent/characters/,target=/app/characters/ --env-file /var/run/agent/secrets/env --rm --name "agent-docker.service" --entrypoint /opt/agent/docker-entrypoint-strace2.sh groq +#100755 > + diff --git a/run_with_groq_docker.sh b/run_with_groq_docker.sh new file mode 100755 index 00000000000..ee3145759e4 --- /dev/null +++ b/run_with_groq_docker.sh @@ -0,0 +1,30 @@ + +# +bash ./get_secrets.sh + +docker kill agent-docker.service || echo skip +docker rm --force agent-docker.service || echo skip + +export CORE_AGENT_IMAGE=h4ckermike/elizaos-eliza:feature-arm64_fastembed +export TOKENIZERS_IMAGE=h4ckermike/arm64-tokenizers:feature-arm64 +# AUDIO +# video +# more +/usr/bin/docker pull $TOKENIZERS_IMAGE +/usr/bin/docker pull $CORE_AGENT_IMAGE + +# intialize the volume as side effect +docker run -v tokenizer:/node_modules/tokenizers/ $TOKENIZERS_IMAGE +#docker cp characters/eliza.character.json agent-docker.service:/app/agent/characters/eliza.character.json +#docker commit agent-docker.service groq + +# now bind it in +/usr/bin/docker run -d -p 3000:3000 \ + -v tokenizer:/app/node_modules/@anush008/tokenizers/ -v tokenizer:/app/node_modules/fastembed/node_modules/.pnpm/@anush008+tokenizers@https+++codeload.github.com+meta-introspector+arm64-tokenizers+tar.gz+98_s2457qj3pe4ojcbckddasgzfvu/node_modules/@anush008/ \ + --mount type=bind,source=/opt/agent,target=/opt/agent \ + --mount type=bind,source=/opt/agent/characters/,target=/app/characters/ \ + --env-file /var/run/agent/secrets/env \ + --rm \ + --name "agent-docker.service" \ + --entrypoint /opt/agent/docker-entrypoint-strace2.sh $DOCKERIMAGE + diff --git a/rundocker.sh b/rundocker.sh new file mode 100755 index 00000000000..ce8dca3a07d --- /dev/null +++ b/rundocker.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# FIXME move this and related files into the user data via templates and compression +# this is the install script +# install_script = "/opt/agent/rundocker.sh" +# called on boot. +echo using "${AGENT_NAME}" as agent name base for keys +export AGENT_NAME +#pwd +#ls -latr +#. ./.env # for secrets +set -e # stop on any error +export WORKSOURCE="/opt/agent" + +echo for now install helper tools +snap install aws-cli --classic +apt install -y jq +apt install -y lsof strace nmap +#apt install -y emacs-nox + +if ! id -u agent > /dev/null 2>&1; then + adduser --disabled-password --gecos "" agent --home "/home/agent" || echo ignore +else + echo "User agent already exists, ignoring..." +fi + +git config --global --add safe.directory "/opt/agent" +cd "/opt/agent/" || exit 1 # "we need agent" +#git log -1 +mkdir -p "/home/agent" +mkdir -p "/var/agent/logs" +chown -R agent:agent "/var/agent/" "/home/agent" "/opt/agent" +mkdir -p "/var/run/agent/secrets/" + +bash ./get_secrets.sh + +if ! grep -q "^HOME" "/var/run/agent/secrets/env"; then + echo "HOME=/home/agent" >> "/var/run/agent/secrets/env" +fi +if ! grep -q "^HOME" "/var/run/agent/secrets/env"; then + echo "WORKSPACE_DIR=\${STATE_DIRECTORY}" >> "/var/run/agent/secrets/env" +fi +cp "${WORKSOURCE}/systemd/agent-docker.service" /etc/systemd/system/agent-docker.service +grep . -h -n /etc/systemd/system/agent-docker.service +chown -R agent:agent /var/run/agent/ +chown -R agent:agent /opt/agent/ +systemctl daemon-reload + +# now we can kill any existing +docker stop agent-docker.service || echo oops +docker kill agent-docker.service || echo oops +docker rm agent-docker.service || echo oops + + +systemctl start agent-docker || echo failed +systemctl enable agent-docker || echo failed +#systemctl status agent-docker || echo oops2 diff --git a/scripts/clean.sh b/scripts/clean.sh new file mode 100644 index 00000000000..9c687aa40cb --- /dev/null +++ b/scripts/clean.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Navigate to the script's directory +cd "$(dirname "$0")"/.. +echo "Cleanup started." +# Find and remove node_modules directories, dist directories. +find . -type d -name "node_modules" -print0 | xargs -0 rm -rf +find . -type d -name "dist" -exec rm -rf {} + +find . -type d -name ".turbo" -exec rm -rf {} + + +# Remove core cache +rm -rf ./packages/core/cache + +# Remove pnpm lockfile +rm -f ./pnpm-lock.yaml + +echo "Cleanup completed." +exit 0 diff --git a/scripts/repomix-full.config.json b/scripts/repomix-full.config.json new file mode 100644 index 00000000000..5a0bc2a0166 --- /dev/null +++ b/scripts/repomix-full.config.json @@ -0,0 +1,75 @@ +{ + "output": { + "filePath": "packages/docs/static/llms-full.txt", + "style": "markdown", + "compress": true, + "fileSummary": true, + "directoryStructure": true, + "removeComments": true, + "removeEmptyLines": true, + "showLineNumbers": false, + "includeEmptyDirectories": false, + "topFilesLength": 10, + "headerText": "ElizaOS Developer Context - Core technical components and implementation details", + "instructionFilePath": "scripts/dev-instructions.md" + }, + "include": [ + "packages/docs/docs/core/overview.md", + "packages/docs/docs/quickstart.md", + "packages/docs/docs/core/actions.md", + "packages/docs/docs/core/knowledge.md", + "packages/docs/docs/core/database.md", + "packages/core/src/types.ts", + "packages/core/src/runtime.ts", + "packages/core/src/bootstrap.ts", + "packages/core/src/database.ts", + "packages/core/src/actions.ts", + "packages/core/src/entities.ts", + "packages/core/src/prompts.ts", + "packages/core/src/uuid.ts", + "packages/core/src/logger.ts", + "packages/core/src/providers/actions.ts", + "packages/core/src/providers/character.ts", + "packages/core/src/providers/knowledge.ts", + "packages/core/src/providers/recentMessages.ts", + "packages/core/src/providers/relationships.ts", + "packages/core/src/providers/evaluators.ts", + "packages/core/src/providers/settings.ts", + "packages/core/src/actions/reply.ts", + "packages/core/src/actions/sendMessage.ts", + "packages/cli/src/index.ts", + "packages/cli/src/commands/agent.ts", + "packages/cli/src/commands/start.ts", + "packages/cli/src/commands/test.ts", + "packages/cli/src/commands/create.ts", + "packages/cli/src/commands/env.ts", + "packages/client/src/lib/api.ts", + "packages/client/src/types/index.ts", + "packages/client/src/hooks/use-agent-management.ts", + "README.md", + "package.json", + ".env.example" + ], + "ignore": { + "useGitignore": true, + "useDefaultPatterns": true, + "customPatterns": [ + "**/*.test.ts", + "**/__tests__/**", + "**/node_modules/**", + "packages/docs/community/**", + "packages/docs/news/**", + "packages/plugin-*/**", + "**/*.ico", + "**/*.png", + "**/*.jpg", + "**/*.svg" + ] + }, + "security": { + "enableSecurityCheck": true + }, + "tokenCount": { + "encoding": "cl100k_base" + } +} diff --git a/scripts/repomix.config.json b/scripts/repomix.config.json index f587d7191f9..1e649e64ecc 100644 --- a/scripts/repomix.config.json +++ b/scripts/repomix.config.json @@ -19,7 +19,6 @@ "packages/docs/docs/core/overview.md", "packages/docs/docs/core/actions.md", "packages/docs/docs/core/agents.md", - "packages/docs/docs/core/clients.md", "packages/docs/docs/core/database.md", "packages/docs/docs/core/evaluators.md", "packages/docs/docs/core/knowledge.md", diff --git a/set_secrets.sh b/set_secrets.sh new file mode 100755 index 00000000000..086a9791ddf --- /dev/null +++ b/set_secrets.sh @@ -0,0 +1,28 @@ +#set +x # turn off logging +export AGENT_IMAGE=h4ckermike/elizaos-eliza:feature-arm64_fastembed +export TOKENIZER_IMAGE=h4ckermike/arm64-tokenizers:feature-arm64 + +# sets the parameter +#aws ssm put-parameter --name "agent_openai_key" --value "${OPENAI_API_KEY}" --type String +aws ssm put-parameter --overwrite --name "tine_agent_twitter_password" --value "${TWITTER_PASSWORD}" --type String +aws ssm put-parameter --overwrite --name "tine_agent_twitter_email" --value "${TWITTER_EMAIL}" --type String +aws ssm put-parameter --overwrite --name "tine_agent_twitter_username" --value "${TWITTER_USERNAME}" --type String +#aws ssm put-parameter --name "tine_agent_openai_key" --value "${OPENAI_API_KEY}" --type String +#aws ssm put-parameter --name "tine_agent_openai_endpoint" --value "${OPENAI_API_BASE}" --type String +#aws ssm put-parameter --name "tine_agent_openai_model" --value "${LLMMODEL}" --type String +aws ssm put-parameter --name "tine_agent_groq_key" --value "${GROQ_API_KEY}" --type String + +aws ssm put-parameter --name "tine_agent_agent_image" --value "${AGENT_IMAGE}" --type String +# aws ssm put-parameter --name "tine_agent_agent_image" --value "${AGENT_IMAGE}" --type String --region us-east-1 --overwrite +aws ssm put-parameter --name "tine_agent_tokenizer_image" --value "${TOKENIZER_IMAGE}" --type String +#aws ssm put-parameter --name "tine_agent_tokenizer_image" --value "${TOKENIZER_IMAGE}" --type String --region us-east-1 --overwrite + + + + +aws ssm put-parameter --name "tine_agent_2_agent_image" --value "h4ckermike/elizaos-eliza:feb10" --type String +aws ssm put-parameter --name "tine_agent_2_docker_username" --value "${DOCKER_USERNAME}" --type String +aws ssm put-parameter --name "tine_agent_2_docker_password" --value "${DOCKER_PASSWORD}" --type String + + +# aws ssm put-parameter --name "tine_agent_2_docker_username" --value "${DOCKER_USERNAME}" --type String --profile solfunmeme_dev diff --git a/set_systemd.sh b/set_systemd.sh new file mode 100755 index 00000000000..e35953ad173 --- /dev/null +++ b/set_systemd.sh @@ -0,0 +1,2 @@ +#!/bin/bash +source /var/run/agent/secrets/env diff --git a/ssh-ssm.py b/ssh-ssm.py new file mode 100755 index 00000000000..94964c87a73 --- /dev/null +++ b/ssh-ssm.py @@ -0,0 +1,45 @@ +#!/usr/bin/python +import time +import json +import boto3 +#from dateutil import tz + + +def parse_command_id(send_command_output): + return send_command_output['Command']['CommandId'] + +def fwd(instance): + # https://aws.amazon.com/blogs/aws/new-port-forwarding-using-aws-system-manager-sessions-manager/ + #INSTANCE_ID=$(aws ec2 describe-instances --filter "Name=tag:Name,Values=CodeStack/NewsBlogInstance" --query "Reservations[].Instances[?State.Name == 'running'].InstanceId[]" --output text) +# create the port forwarding tunnel + prms = { + "portNumber":["22"], + "localPortNumber":["2222"] + } + prms_jsn = json.dumps(prms) + print(f"""aws ssm start-session --target {instance} --document-name AWS-StartPortForwardingSession --parameters '{prms_jsn}'""") + +def main(): + ec2_client = boto3.client('ec2') + ssm_client = boto3.client('ssm') + + # Get the list of instance IDs and their states + instances_response = ec2_client.describe_instances() + + instances = [ + (instance['InstanceId'], instance['State']['Name']) + for reservation in instances_response['Reservations'] + for instance in reservation['Instances'] + ] + for reservation in instances_response['Reservations']: + for instance in reservation['Instances']: + print(instance) + instance_id = instance['InstanceId'] + state = instance['State']['Name'] + if state == 'running': + #print(f"Starting command for instance: {instance_id}") + #print(f"aws ssm start-session --target {instance_id}") + fwd(instance_id) + +if __name__ == "__main__": + main() diff --git a/systemd/agent-docker-it.sh b/systemd/agent-docker-it.sh new file mode 100644 index 00000000000..831a77b0803 --- /dev/null +++ b/systemd/agent-docker-it.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +source /var/run/agent/secrets/env + +/usr/bin/docker run -p 3000:3000 \ + -v tokenizer:/app/node_modules/@anush008/tokenizers/ \ + -v tokenizer:/app/node_modules/fastembed/node_modules/.pnpm/@anush008+tokenizers@https+++codeload.github.com+meta-introspector+arm64-tokenizers+tar.gz+98_s2457qj3pe4ojcbckddasgzfvu/node_modules/@anush008/ \ + --mount type=bind,source=/opt/agent,target=/opt/agent \ + --env-file /var/run/agent/secrets/env \ + --name "agent-docker.service" --entrypoint "" -it ${AGENT_IMAGE} bash + + + diff --git a/systemd/agent-docker-local-it.sh b/systemd/agent-docker-local-it.sh new file mode 100644 index 00000000000..5dce24143f3 --- /dev/null +++ b/systemd/agent-docker-local-it.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +source ./env +/usr/bin/docker kill agent-docker.service || echo ok +/usr/bin/docker remove agent-docker.service || echo ok + +/usr/bin/docker run -p 3000:3000 \ + -v tokenizer:/app/node_modules/@anush008/tokenizers/ \ + -v tokenizer:/app/node_modules/fastembed/node_modules/.pnpm/@anush008+tokenizers@https+++codeload.github.com+meta-introspector+arm64-tokenizers+tar.gz+98_s2457qj3pe4ojcbckddasgzfvu/node_modules/@anush008/ \ + --mount type=bind,source=/opt/agent,target=/opt/agent \ + --env-file env \ + --name "agent-docker.service" --entrypoint "" -it ${AGENT_IMAGE} bash diff --git a/systemd/agent-docker-local.sh b/systemd/agent-docker-local.sh new file mode 100644 index 00000000000..97f1b380dfb --- /dev/null +++ b/systemd/agent-docker-local.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +source ./env +/usr/bin/docker remove agent-docker.service + +/usr/bin/docker run -p 3000:3000 \ + -v tokenizer:/app/node_modules/@anush008/tokenizers/ \ + -v tokenizer:/app/node_modules/fastembed/node_modules/.pnpm/@anush008+tokenizers@https+++codeload.github.com+meta-introspector+arm64-tokenizers+tar.gz+98_s2457qj3pe4ojcbckddasgzfvu/node_modules/@anush008/ \ + --mount type=bind,source=/opt/agent,target=/opt/agent \ + --env-file env \ + --name "agent-docker.service" \ + --entrypoint /opt/agent/docker-entrypoint-strace2.sh ${AGENT_IMAGE} + diff --git a/systemd/agent-docker.service b/systemd/agent-docker.service new file mode 100644 index 00000000000..cb04d270eb7 --- /dev/null +++ b/systemd/agent-docker.service @@ -0,0 +1,38 @@ +# derived from https://phil.lavin.me.uk/2021/12/running-docker-containers-from-aws-ecr-with-systemd/ +# derived from https://github.com/encode/uvicorn/issues/678 +# derived from https://blog.container-solutions.com/running-docker-containers-with-systemd + +[Unit] +Description=agent +After=docker.service +Requires=docker.service +StartLimitInterval=200 +StartLimitBurst=10 + +[Service] +EnvironmentFile=/var/run/agent/secrets/env +RestartSec=10 +TimeoutStartSec=0 +ExecStartPre=-/usr/bin/docker exec %n stop || echo cannot prestop +ExecStartPre=-/usr/bin/docker rm %n || echo cannot preremove +ExecStartPre=/usr/bin/docker pull ${AGENT_IMAGE} +ExecStartPre=/usr/bin/docker pull ${TOKENIZER_IMAGE} +ExecStartPre=-/usr/bin/docker run --name copytoken \ + -v tokenizer:/node_modules/tokenizers/ \ + ${TOKENIZER_IMAGE} +ExecStart=/usr/bin/docker run \ + -p 3000:3000 \ + -v tokenizer:/app/node_modules/@anush008/tokenizers/ \ + -v tokenizer:/app/node_modules/fastembed/node_modules/.pnpm/@anush008+tokenizers@https+++codeload.github.com+meta-introspector+arm64-tokenizers+tar.gz+98_s2457qj3pe4ojcbckddasgzfvu/node_modules/@anush008/ \ + --mount type=bind,source=/opt/agent,target=/opt/agent \ + --env-file /var/run/agent/secrets/env \ + --name "agent-docker.service" \ + --entrypoint /opt/agent/docker-entrypoint-none.sh \ + ${AGENT_IMAGE} +StandardOutput=file:/var/log/agent_systemd.log +StandardError=file:/var/log/agent_systemd.log +ExecReload=/bin/kill -HUP ${MAINPID} +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/systemd/agent-docker.sh b/systemd/agent-docker.sh new file mode 100644 index 00000000000..fb522b5ec2e --- /dev/null +++ b/systemd/agent-docker.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +export $(source /var/run/agent/secrets/env| xargs) + +docker kill "agent-docker.service" +docker rm "agent-docker.service" +/usr/bin/docker run -p 3000:3000 \ + -v tokenizer:/app/node_modules/@anush008/tokenizers/ \ + -v tokenizer:/app/node_modules/fastembed/node_modules/.pnpm/@anush008+tokenizers@https+++codeload.github.com+meta-introspector+arm64-tokenizers+tar.gz+98_s2457qj3pe4ojcbckddasgzfvu/node_modules/@anush008/ \ + --mount type=bind,source=/opt/agent,target=/opt/agent \ + --env-file /var/run/agent/secrets/env \ + --name "agent-docker.service" \ + --entrypoint /opt/agent/docker-entrypoint-strace2.sh ${AGENT_IMAGE} + diff --git a/tee-docker-compose.yaml b/tee-docker-compose.yaml new file mode 100644 index 00000000000..c4d2e97ed4d --- /dev/null +++ b/tee-docker-compose.yaml @@ -0,0 +1,65 @@ +version: '3' +services: + postgres: + image: postgres:15 + environment: + - POSTGRES_PASSWORD=postgres + - POSTGRES_USER=postgres + - POSTGRES_DB=eliza + volumes: + - postgres-data:/root/.eliza/db + ports: + - '127.0.0.1:5432:5432' + healthcheck: + test: ['CMD-SHELL', 'pg_isready -U postgres'] + interval: 5s + timeout: 5s + retries: 5 + networks: + - eliza-network + restart: always + eliza: + image: ${DOCKER_IMAGE_FULL_NAME} + container_name: elizav2 + command: bun run start + stdin_open: true + tty: true + volumes: + - /var/run/tappd.sock:/var/run/tappd.sock + environment: + - OPENAI_API_KEY=${OPENAI_API_KEY} + - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} + - SERVER_PORT=${SERVER_PORT} + - EVM_CHAINS=${EVM_CHAINS} + - BIRDEYE_API_KEY=${BIRDEYE_API_KEY} + - COMMUNITY_MANAGER_DISCORD_APPLICATION_ID=${COMMUNITY_MANAGER_DISCORD_APPLICATION_ID} + - COMMUNITY_MANAGER_DISCORD_API_TOKEN=${COMMUNITY_MANAGER_DISCORD_API_TOKEN} + - SOCIAL_MEDIA_MANAGER_DISCORD_APPLICATION_ID=${SOCIAL_MEDIA_MANAGER_DISCORD_APPLICATION_ID} + - SOCIAL_MEDIA_MANAGER_DISCORD_API_TOKEN=${SOCIAL_MEDIA_MANAGER_DISCORD_API_TOKEN} + - LIAISON_DISCORD_APPLICATION_ID=${LIAISON_DISCORD_APPLICATION_ID} + - LIAISON_DISCORD_API_TOKEN=${LIAISON_DISCORD_API_TOKEN} + - PROJECT_MANAGER_DISCORD_APPLICATION_ID=${PROJECT_MANAGER_DISCORD_APPLICATION_ID} + - PROJECT_MANAGER_DISCORD_API_TOKEN=${PROJECT_MANAGER_DISCORD_API_TOKEN} + - DEV_REL_DISCORD_APPLICATION_ID=${DEV_REL_DISCORD_APPLICATION_ID} + - DEV_REL_DISCORD_API_TOKEN=${DEV_REL_DISCORD_API_TOKEN} + - INVESTMENT_MANAGER_DISCORD_APPLICATION_ID=${INVESTMENT_MANAGER_DISCORD_APPLICATION_ID} + - INVESTMENT_MANAGER_DISCORD_API_TOKEN=${INVESTMENT_MANAGER_DISCORD_API_TOKEN} + - PGLITE_DATA_DIR=/root/.eliza/db + - TEE_MODE=${TEE_MODE} + - WALLET_SECRET_SALT=${WALLET_SECRET_SALT} + - TEE_VENDOR=${TEE_VENDOR} + ports: + - '3000:3000' + depends_on: + postgres: + condition: service_healthy + restart: always + networks: + - eliza-network + +networks: + eliza-network: + driver: bridge + +volumes: + postgres-data: diff --git a/update.sh b/update.sh new file mode 100755 index 00000000000..1b0d2e23768 --- /dev/null +++ b/update.sh @@ -0,0 +1,5 @@ +aws ssm update-document \ + + --name "UpdateEliza" \ + --content "file://UpdateEliza.yaml" \ + --document-version '$LATEST' diff --git a/vendor/elizaos/agent-twitter-client b/vendor/elizaos/agent-twitter-client new file mode 160000 index 00000000000..d85f9a90e71 --- /dev/null +++ b/vendor/elizaos/agent-twitter-client @@ -0,0 +1 @@ +Subproject commit d85f9a90e718edbf28ce23f03bae7302df803cd1 diff --git a/vendor/elizaos/client-telegram b/vendor/elizaos/client-telegram new file mode 160000 index 00000000000..c6b09657ba6 --- /dev/null +++ b/vendor/elizaos/client-telegram @@ -0,0 +1 @@ +Subproject commit c6b09657ba6bcad1ea9750216e46033e2310bf12 diff --git a/vendor/elizaos/client-twitter b/vendor/elizaos/client-twitter new file mode 160000 index 00000000000..47efd360959 --- /dev/null +++ b/vendor/elizaos/client-twitter @@ -0,0 +1 @@ +Subproject commit 47efd36095910e708c91e48574323b5e1ca7b38e diff --git a/vendor/elizaos/plugin-speech-tts b/vendor/elizaos/plugin-speech-tts new file mode 160000 index 00000000000..56cfd540a5d --- /dev/null +++ b/vendor/elizaos/plugin-speech-tts @@ -0,0 +1 @@ +Subproject commit 56cfd540a5d25e3c863dd21a1607a2c3b1c45f76 diff --git a/vendor/elizaos/plugin-twitter b/vendor/elizaos/plugin-twitter new file mode 160000 index 00000000000..48f7d4ab3bb --- /dev/null +++ b/vendor/elizaos/plugin-twitter @@ -0,0 +1 @@ +Subproject commit 48f7d4ab3bb9bf58cd363fef142f82dc347952e2