Compare commits
1
Commits
main
..
feat/mobile
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c737ed137d |
@@ -1,16 +0,0 @@
|
||||
# depcheck configuration.
|
||||
#
|
||||
# ignores: dependencies that are present on purpose but never imported directly,
|
||||
# so depcheck's static scan reports them as a false positive.
|
||||
#
|
||||
# The three @opentelemetry/* entries below are all transitive dependencies of
|
||||
# @opentelemetry/sdk-node, which we DO import and drive (NodeSDK in
|
||||
# packages/api/src/telemetry/sdk.ts). They are pinned at the top level to keep
|
||||
# every otel package on one aligned version (mismatched otel versions break at
|
||||
# runtime). None is imported by name, so depcheck flags them — expected, not
|
||||
# dead. Do NOT remove them (that would unpin the otel version set). Only
|
||||
# @opentelemetry/api is imported directly and stays checked.
|
||||
ignores:
|
||||
- "@opentelemetry/core"
|
||||
- "@opentelemetry/exporter-trace-otlp-http"
|
||||
- "@opentelemetry/sdk-trace-base"
|
||||
@@ -19,7 +19,7 @@ services:
|
||||
# - /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- HOST=0.0.0.0
|
||||
- MONGO_URI=mongodb://mongodb:27017/Chat
|
||||
- MONGO_URI=mongodb://mongodb:27017/LibreChat
|
||||
# - OPENAI_REVERSE_PROXY=http://host.docker.internal:8070/v1
|
||||
- MEILI_HOST=http://meilisearch:7700
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ services:
|
||||
gitnexus:
|
||||
# Override via GITNEXUS_IMAGE in /opt/gitnexus/.env to use a fork or
|
||||
# a pinned version tag like :v1.5.3 for reproducible rollbacks.
|
||||
image: ${GITNEXUS_IMAGE:-ghcr.io/danny-avila/chat-gitnexus:latest}
|
||||
image: ${GITNEXUS_IMAGE:-ghcr.io/danny-avila/librechat-gitnexus:latest}
|
||||
container_name: gitnexus
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
||||
@@ -14,10 +14,10 @@ export NODE_OPTIONS="${NODE_OPTIONS:---max-old-space-size=1280}"
|
||||
# metadata pointer without touching the index data.
|
||||
#
|
||||
# Registration failure handling:
|
||||
# - main (Chat) and dev (Chat-dev) are critical. If either
|
||||
# - main (LibreChat) and dev (LibreChat-dev) are critical. If either
|
||||
# fails to register, exit 1 so docker marks the container unhealthy
|
||||
# and the deploy workflow's readiness check surfaces the error.
|
||||
# - PR indexes (Chat-pr-*) are best-effort. A corrupt PR index
|
||||
# - PR indexes (LibreChat-pr-*) are best-effort. A corrupt PR index
|
||||
# shouldn't take the whole server down.
|
||||
if [ -d /indexes ]; then
|
||||
for dir in /indexes/*/; do
|
||||
@@ -27,7 +27,7 @@ if [ -d /indexes ]; then
|
||||
echo "Registering index: $name"
|
||||
if ! gitnexus index "$dir" --allow-non-git; then
|
||||
case "$name" in
|
||||
Chat|Chat-dev)
|
||||
LibreChat|LibreChat-dev)
|
||||
echo "ERROR: failed to register critical index $name" >&2
|
||||
exit 1
|
||||
;;
|
||||
|
||||
+5
-16
@@ -117,17 +117,6 @@ PROXY=
|
||||
# Endpoint: https://api.hanzo.ai/v1
|
||||
HANZO_API_KEY=
|
||||
|
||||
# Canonical Hanzo Cloud agents (/v1/agents). Lets signed-in users run their own
|
||||
# cloud agents from chat via `/agent <name>` or the @mention picker. The chat
|
||||
# backend proxies /v1/chat/agents/cloud/* to this host, forwarding the user's
|
||||
# hanzo.id token server-side (never to the browser); cloud scopes to their org.
|
||||
# Optional: if unset, derived from OPENAI_BASE_URL (its host, minus /v1).
|
||||
# HANZO_CLOUD_URL=https://api.hanzo.ai
|
||||
# A cloud-agent run is a real billable completion; these bound abuse of the proxy.
|
||||
# CLOUD_AGENT_USER_MAX=30 # max cloud-agent requests per user per window
|
||||
# CLOUD_AGENT_WINDOW=1 # rate-limit window, minutes
|
||||
# CLOUD_AGENT_MAX_CONCURRENT=50 # process-wide in-flight ceiling to cloud (503 past it)
|
||||
|
||||
#===================================#
|
||||
# Known Endpoints - chat.yaml #
|
||||
#===================================#
|
||||
@@ -484,7 +473,7 @@ ALLOW_PASSWORD_RESET=false
|
||||
# server-side to the free model only and rejected from every other route.
|
||||
ALLOW_GUEST_CHAT=false
|
||||
# GUEST_MESSAGE_MAX=3 # free messages per IP before login is required
|
||||
# GUEST_ENDPOINT=Hanzo # custom endpoint name from chat.yaml (api.hanzo.ai)
|
||||
# GUEST_ENDPOINT=Hanzo # custom endpoint name from librechat.yaml (api.hanzo.ai)
|
||||
# GUEST_MODEL=zen3-nano # free Zen model id guests are pinned to
|
||||
# GUEST_TOKEN_EXPIRY=3600000 # guest JWT lifetime in ms (default 1h)
|
||||
# GUEST_TOKEN_MAX=20 # max guest sessions issued per IP per window
|
||||
@@ -775,7 +764,7 @@ HELP_AND_FAQ_URL=https://hanzo.ai/chat
|
||||
# Use environment variable name for dynamic prefix (recommended for cloud deployments)
|
||||
# REDIS_KEY_PREFIX_VAR=K_REVISION
|
||||
# Or use static prefix directly
|
||||
# REDIS_KEY_PREFIX=chat
|
||||
# REDIS_KEY_PREFIX=librechat
|
||||
|
||||
# Redis connection limits
|
||||
# REDIS_MAX_LISTENERS=40
|
||||
@@ -839,8 +828,8 @@ OPENWEATHER_API_KEY=
|
||||
# "Run Code" routes through the Hanzo unified backend (api.hanzo.ai/v1/exec),
|
||||
# which executes in a Hanzo sandbox. execute_code POSTs {BASEURL}/exec with
|
||||
# X-API-Key. https://hanzo.ai/docs/chat/code-interpreter
|
||||
# CHAT_CODE_BASEURL=https://api.hanzo.ai/v1
|
||||
# CHAT_CODE_API_KEY=your-key # prod: KMS chat-secrets/CHAT_CODE_API_KEY
|
||||
# LIBRECHAT_CODE_BASEURL=https://api.hanzo.ai/v1
|
||||
# LIBRECHAT_CODE_API_KEY=your-key # prod: KMS chat-secrets/LIBRECHAT_CODE_API_KEY
|
||||
|
||||
#======================#
|
||||
# Web Search #
|
||||
@@ -848,7 +837,7 @@ OPENWEATHER_API_KEY=
|
||||
|
||||
# Web Search routes through the Hanzo unified backend ONLY — no external SaaS.
|
||||
# The searxng provider + firecrawl scraper both point at api.hanzo.ai/v1/websearch
|
||||
# (Hanzo metasearch + Hanzo Crawl). See chat.yaml `webSearch`.
|
||||
# (Hanzo metasearch + Hanzo Crawl). See librechat.yaml `webSearch`.
|
||||
# https://hanzo.ai/docs/chat/features/web_search
|
||||
# SEARXNG_INSTANCE_URL=https://api.hanzo.ai/v1/websearch
|
||||
# FIRECRAWL_API_URL=https://api.hanzo.ai/v1/websearch
|
||||
|
||||
+20
-20
@@ -1,10 +1,10 @@
|
||||
#=====================================================================#
|
||||
# Chat Configuration #
|
||||
# LibreChat Configuration #
|
||||
#=====================================================================#
|
||||
# Please refer to the reference documentation for assistance #
|
||||
# with configuring your Chat environment. #
|
||||
# with configuring your LibreChat environment. #
|
||||
# #
|
||||
# https://hanzo.ai/docs/chat/configuration/dotenv #
|
||||
# https://www.librechat.ai/docs/configuration/dotenv #
|
||||
#=====================================================================#
|
||||
|
||||
#==================================================#
|
||||
@@ -14,7 +14,7 @@
|
||||
HOST=localhost
|
||||
PORT=3080
|
||||
|
||||
MONGO_URI=mongodb://127.0.0.1:27017/Chat
|
||||
MONGO_URI=mongodb://127.0.0.1:27017/LibreChat
|
||||
|
||||
DOMAIN_CLIENT=http://localhost:3080
|
||||
DOMAIN_SERVER=http://localhost:3080
|
||||
@@ -52,7 +52,7 @@ DEBUG_CONSOLE=false
|
||||
#===============#
|
||||
# Use an absolute path, a relative path, or a URL
|
||||
|
||||
# CONFIG_PATH="/alternative/path/to/chat.yaml"
|
||||
# CONFIG_PATH="/alternative/path/to/librechat.yaml"
|
||||
|
||||
#===================================================#
|
||||
# Endpoints #
|
||||
@@ -63,9 +63,9 @@ DEBUG_CONSOLE=false
|
||||
PROXY=
|
||||
|
||||
#===================================#
|
||||
# Known Endpoints - chat.yaml #
|
||||
# Known Endpoints - librechat.yaml #
|
||||
#===================================#
|
||||
# https://hanzo.ai/docs/chat/configuration/chat_yaml/ai_endpoints
|
||||
# https://www.librechat.ai/docs/configuration/librechat_yaml/ai_endpoints
|
||||
|
||||
# ANYSCALE_API_KEY=
|
||||
# APIPIE_API_KEY=
|
||||
@@ -96,8 +96,8 @@ ANTHROPIC_API_KEY=user_provided
|
||||
#============#
|
||||
|
||||
# Note: these variables are DEPRECATED
|
||||
# Use the `chat.yaml` configuration for `azureOpenAI` instead
|
||||
# You may also continue to use them if you opt out of using the `chat.yaml` configuration
|
||||
# Use the `librechat.yaml` configuration for `azureOpenAI` instead
|
||||
# You may also continue to use them if you opt out of using the `librechat.yaml` configuration
|
||||
|
||||
# AZURE_OPENAI_DEFAULT_MODEL=gpt-3.5-turbo # Deprecated
|
||||
# AZURE_OPENAI_MODELS=gpt-3.5-turbo,gpt-4 # Deprecated
|
||||
@@ -207,7 +207,7 @@ ASSISTANTS_API_KEY=user_provided
|
||||
# The models for Azure Assistants are also determined by your Azure OpenAI configuration.
|
||||
|
||||
# More info, including how to enable use of Assistants with Azure here:
|
||||
# https://hanzo.ai/docs/chat/configuration/chat_yaml/ai_endpoints/azure#using-assistants-with-azure
|
||||
# https://www.librechat.ai/docs/configuration/librechat_yaml/ai_endpoints/azure#using-assistants-with-azure
|
||||
|
||||
#============#
|
||||
# Plugins #
|
||||
@@ -320,7 +320,7 @@ TTS_API_KEY=
|
||||
#==================================================#
|
||||
# RAG #
|
||||
#==================================================#
|
||||
# More info: https://hanzo.ai/docs/chat/configuration/rag_api
|
||||
# More info: https://www.librechat.ai/docs/configuration/rag_api
|
||||
|
||||
# RAG_OPENAI_BASEURL=
|
||||
# RAG_OPENAI_API_KEY=
|
||||
@@ -513,7 +513,7 @@ EMAIL_ALLOW_SELFSIGNED=
|
||||
EMAIL_USERNAME=
|
||||
EMAIL_PASSWORD=
|
||||
EMAIL_FROM_NAME=
|
||||
EMAIL_FROM=noreply@hanzo.ai
|
||||
EMAIL_FROM=noreply@librechat.ai
|
||||
|
||||
#========================#
|
||||
# Mailgun API #
|
||||
@@ -522,7 +522,7 @@ EMAIL_FROM=noreply@hanzo.ai
|
||||
# MAILGUN_API_KEY=your-mailgun-api-key
|
||||
# MAILGUN_DOMAIN=mg.yourdomain.com
|
||||
# EMAIL_FROM=noreply@yourdomain.com
|
||||
# EMAIL_FROM_NAME="Chat"
|
||||
# EMAIL_FROM_NAME="LibreChat"
|
||||
|
||||
# # Optional: For EU region
|
||||
# MAILGUN_HOST=https://api.eu.mailgun.net
|
||||
@@ -572,16 +572,16 @@ ALLOW_SHARED_LINKS_PUBLIC=true
|
||||
# STATIC_CACHE_MAX_AGE=172800
|
||||
# STATIC_CACHE_S_MAX_AGE=86400
|
||||
|
||||
# If you have another service in front of your Chat doing compression, disable express based compression here
|
||||
# If you have another service in front of your LibreChat doing compression, disable express based compression here
|
||||
# DISABLE_COMPRESSION=true
|
||||
|
||||
#===================================================#
|
||||
# UI #
|
||||
#===================================================#
|
||||
|
||||
APP_TITLE=Chat
|
||||
APP_TITLE=LibreChat
|
||||
# CUSTOM_FOOTER="My custom footer"
|
||||
HELP_AND_FAQ_URL=https://hanzo.chat
|
||||
HELP_AND_FAQ_URL=https://librechat.ai
|
||||
|
||||
# SHOW_BIRTHDAY_ICON=true
|
||||
|
||||
@@ -630,11 +630,11 @@ HELP_AND_FAQ_URL=https://hanzo.chat
|
||||
OPENWEATHER_API_KEY=
|
||||
|
||||
#====================================#
|
||||
# Chat Code Interpreter API #
|
||||
# LibreChat Code Interpreter API #
|
||||
#====================================#
|
||||
|
||||
# https://code.hanzo.ai
|
||||
# CHAT_CODE_API_KEY=your-key
|
||||
# https://code.librechat.ai
|
||||
# LIBRECHAT_CODE_API_KEY=your-key
|
||||
|
||||
#======================#
|
||||
# Web Search #
|
||||
@@ -644,7 +644,7 @@ OPENWEATHER_API_KEY=
|
||||
# Omit values to allow user to provide them.
|
||||
|
||||
# For more information on configuration values, see:
|
||||
# https://hanzo.ai/docs/chat/features/web_search
|
||||
# https://librechat.ai/docs/features/web_search
|
||||
|
||||
# Search Provider (Required)
|
||||
# SERPER_API_KEY=your_serper_api_key
|
||||
|
||||
+7
-7
@@ -6,15 +6,15 @@ OPENAI_API_KEY=sk-hanzo-your-api-key-here
|
||||
OPENAI_BASE_URL=https://api.hanzo.ai/v1
|
||||
|
||||
# Code Interpreter ("Run Code") — Hanzo unified backend.
|
||||
# Chat's execute_code tool POSTs {CHAT_CODE_BASEURL}/exec with header
|
||||
# LibreChat's execute_code tool POSTs {LIBRECHAT_CODE_BASEURL}/exec with header
|
||||
# X-API-Key. cloud-api serves /v1/exec (-> sandboxed executor). The key is
|
||||
# KMS-sourced (chat-secrets/CHAT_CODE_API_KEY). These are the ONLY vars
|
||||
# Chat reads — the old CODE_EXECUTION_ENDPOINT/RUNTIME_API_KEY were dead.
|
||||
CHAT_CODE_BASEURL=https://api.hanzo.ai/v1
|
||||
CHAT_CODE_API_KEY=set-in-KMS-chat-secrets
|
||||
# KMS-sourced (chat-secrets/LIBRECHAT_CODE_API_KEY). These are the ONLY vars
|
||||
# LibreChat reads — the old CODE_EXECUTION_ENDPOINT/RUNTIME_API_KEY were dead.
|
||||
LIBRECHAT_CODE_BASEURL=https://api.hanzo.ai/v1
|
||||
LIBRECHAT_CODE_API_KEY=set-in-KMS-chat-secrets
|
||||
|
||||
# Web Search — Hanzo unified backend (searxng + firecrawl compat over Hanzo
|
||||
# search + crawl). See chat.yaml `webSearch`. One shared service key.
|
||||
# search + crawl). See librechat.yaml `webSearch`. One shared service key.
|
||||
SEARXNG_INSTANCE_URL=https://api.hanzo.ai/v1/websearch
|
||||
FIRECRAWL_API_URL=https://api.hanzo.ai/v1/websearch
|
||||
WEBSEARCH_API_KEY=set-in-KMS-chat-secrets
|
||||
@@ -85,5 +85,5 @@ DEBUG_LOGGING=false
|
||||
# ====== NOTES ======
|
||||
# 1. Get your Hanzo API key from https://hanzo.ai/dashboard
|
||||
# 2. All AI providers are accessed through api.hanzo.ai -- no individual keys needed
|
||||
# 3. Model list is configured in chat.yaml under endpoints.custom (Hanzo endpoint)
|
||||
# 3. Model list is configured in librechat.yaml under endpoints.custom (Hanzo endpoint)
|
||||
# 4. zen4 is the default model for new conversations
|
||||
|
||||
@@ -38,7 +38,7 @@ Project maintainers have the right and responsibility to remove, edit, or reject
|
||||
- Install [MongoDB Community Edition](https://www.mongodb.com/docs/manual/administration/install-community/), ensure that `mongosh` connects to your local instance.
|
||||
- Run: `npx install playwright`, then `npx playwright install`.
|
||||
- Copy `config.local`: `cp e2e/config.local.example.ts e2e/config.local.ts`.
|
||||
- Copy `chat.yaml`: `cp chat.example.yaml chat.yaml`.
|
||||
- Copy `librechat.yaml`: `cp librechat.example.yaml librechat.yaml`.
|
||||
- Run: `npm run e2e`.
|
||||
|
||||
## 2. Development Notes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CHART_PATH="${CHART_PATH:-helm/chat/Chart.yaml}"
|
||||
CHART_PATH="${CHART_PATH:-helm/librechat/Chart.yaml}"
|
||||
DEFAULT_BRANCH="${DEFAULT_BRANCH:-main}"
|
||||
BASE_REF="${BASE_REF:-refs/remotes/origin/${DEFAULT_BRANCH}}"
|
||||
BACKFILL_FROM_VERSION="${BACKFILL_FROM_VERSION:-1.9.0}"
|
||||
|
||||
@@ -67,11 +67,11 @@ jobs:
|
||||
- name: Run unit tests
|
||||
run: cd api && pnpm run test:ci
|
||||
|
||||
- name: Run @hanzochat/data-provider unit tests
|
||||
- name: Run librechat-data-provider unit tests
|
||||
run: cd packages/data-provider && pnpm run test:ci
|
||||
|
||||
- name: Run @hanzochat/data-schemas unit tests
|
||||
- name: Run @librechat/data-schemas unit tests
|
||||
run: cd packages/data-schemas && pnpm run test:ci
|
||||
|
||||
- name: Run @hanzochat/api unit tests
|
||||
- name: Run @librechat/api unit tests
|
||||
run: cd packages/api && pnpm run test:ci
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Publish `@hanzochat/client` to NPM
|
||||
name: Publish `@librechat/client` to NPM
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
working-directory: packages/client
|
||||
run: |
|
||||
PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
||||
PUBLISHED_VERSION=$(npm view @hanzochat/client version 2>/dev/null || echo "0.0.0")
|
||||
PUBLISHED_VERSION=$(npm view @librechat/client version 2>/dev/null || echo "0.0.0")
|
||||
if [ "$PACKAGE_VERSION" = "$PUBLISHED_VERSION" ]; then
|
||||
echo "No version change, skipping publish"
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Publish `@hanzochat/data-provider` to NPM
|
||||
name: Publish `librechat-data-provider` to NPM
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Publish `@hanzochat/data-schemas` to NPM
|
||||
name: Publish `@librechat/data-schemas` to NPM
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
working-directory: packages/data-schemas
|
||||
run: |
|
||||
PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
||||
PUBLISHED_VERSION=$(npm view @hanzochat/data-schemas version 2>/dev/null || echo "0.0.0")
|
||||
PUBLISHED_VERSION=$(npm view @librechat/data-schemas version 2>/dev/null || echo "0.0.0")
|
||||
if [ "$PACKAGE_VERSION" = "$PUBLISHED_VERSION" ]; then
|
||||
echo "No version change, skipping publish"
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
|
||||
@@ -1,14 +1,49 @@
|
||||
# Neutralized — the native deploy pipeline is .hanzo/workflows/deploy.yml
|
||||
# (Hanzo Git push -> in-cluster act_runner -> BuildKit builds ./Dockerfile ->
|
||||
# ghcr.io/hanzoai/chat:<sha> -> kubectl patch app/chat -> operator reconcile).
|
||||
# GitHub is a mirror; this workflow no longer builds, publishes, or deploys.
|
||||
name: "Update Test Server (sync notice)"
|
||||
name: Update Test Server
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Docker Dev Branch Images Build"]
|
||||
types:
|
||||
- completed
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
notice:
|
||||
runs-on: ubuntu-latest
|
||||
deploy:
|
||||
runs-on: hanzo-deploy-linux-amd64
|
||||
if: |
|
||||
github.repository == 'danny-avila/LibreChat' &&
|
||||
(github.event_name == 'workflow_dispatch' ||
|
||||
(github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'dev'))
|
||||
steps:
|
||||
- name: Sync notice
|
||||
run: echo "native pipeline is .hanzo/workflows/deploy.yml; GitHub is a mirror"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install SSH Key
|
||||
uses: shimataro/ssh-key-action@v2
|
||||
with:
|
||||
key: ${{ secrets.DO_SSH_PRIVATE_KEY }}
|
||||
known_hosts: ${{ secrets.DO_KNOWN_HOSTS }}
|
||||
|
||||
- name: Run update script on DigitalOcean Droplet
|
||||
env:
|
||||
DO_HOST: ${{ secrets.DO_HOST }}
|
||||
DO_USER: ${{ secrets.DO_USER }}
|
||||
run: |
|
||||
ssh ${DO_USER}@${DO_HOST} << EOF
|
||||
sudo -i -u danny bash << 'EEOF'
|
||||
cd ~/LibreChat && \
|
||||
git fetch origin main && \
|
||||
sudo npm run stop:deployed && \
|
||||
sudo docker images --format "{{.Repository}}:{{.ID}}" | grep -E "lc-dev|librechat" | cut -d: -f2 | xargs -r sudo docker rmi -f || true && \
|
||||
sudo npm run update:deployed && \
|
||||
git checkout dev && \
|
||||
git pull origin dev && \
|
||||
git checkout do-deploy && \
|
||||
git rebase dev && \
|
||||
sudo npm run start:deployed && \
|
||||
echo "Update completed. Application should be running now."
|
||||
EEOF
|
||||
EOF
|
||||
|
||||
@@ -1,14 +1,95 @@
|
||||
# Neutralized — the native deploy pipeline is .hanzo/workflows/deploy.yml
|
||||
# (Hanzo Git push -> in-cluster act_runner -> BuildKit builds ./Dockerfile ->
|
||||
# ghcr.io/hanzoai/chat:<sha> -> kubectl patch app/chat -> operator reconcile).
|
||||
# GitHub is a mirror; this workflow no longer builds, publishes, or deploys.
|
||||
name: "Docker Dev Branch Images Build (sync notice)"
|
||||
name: Docker Dev Branch Images Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
paths:
|
||||
- 'api/**'
|
||||
- 'client/**'
|
||||
- 'packages/**'
|
||||
- 'package.json'
|
||||
- 'package-lock.json'
|
||||
- 'Dockerfile'
|
||||
- 'Dockerfile.multi'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
notice:
|
||||
runs-on: ubuntu-latest
|
||||
build:
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
timeout-minutes: 130
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: api-build
|
||||
file: Dockerfile.multi
|
||||
image_name: lc-dev-api
|
||||
- target: node
|
||||
file: Dockerfile
|
||||
image_name: lc-dev
|
||||
|
||||
steps:
|
||||
- name: Sync notice
|
||||
run: echo "native pipeline is .hanzo/workflows/deploy.yml; GitHub is a mirror"
|
||||
# Check out the repository
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Set up QEMU
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
# Set up Docker Buildx
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
# Log in to GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Login to Docker Hub
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
# Prepare the environment
|
||||
- name: Prepare environment
|
||||
run: |
|
||||
cp .env.example .env
|
||||
|
||||
- name: Compute build metadata
|
||||
run: |
|
||||
echo "BUILD_COMMIT=${{ github.sha }}" >> $GITHUB_ENV
|
||||
echo "BUILD_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
|
||||
|
||||
# Build and push Docker images for each target
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.file }}
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:${{ github.sha }}
|
||||
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:latest
|
||||
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:${{ github.sha }}
|
||||
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
target: ${{ matrix.target }}
|
||||
build-args: |
|
||||
BUILD_COMMIT=${{ env.BUILD_COMMIT }}
|
||||
BUILD_BRANCH=${{ env.BUILD_BRANCH }}
|
||||
BUILD_DATE=${{ env.BUILD_DATE }}
|
||||
|
||||
@@ -1,14 +1,91 @@
|
||||
# Neutralized — the native deploy pipeline is .hanzo/workflows/deploy.yml
|
||||
# (Hanzo Git push -> in-cluster act_runner -> BuildKit builds ./Dockerfile ->
|
||||
# ghcr.io/hanzoai/chat:<sha> -> kubectl patch app/chat -> operator reconcile).
|
||||
# GitHub is a mirror; this workflow no longer builds, publishes, or deploys.
|
||||
name: "Docker Dev Images Build (sync notice)"
|
||||
name: Docker Dev Images Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'api/**'
|
||||
- 'client/**'
|
||||
- 'packages/**'
|
||||
- 'package.json'
|
||||
- 'package-lock.json'
|
||||
- 'Dockerfile'
|
||||
- 'Dockerfile.multi'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
notice:
|
||||
runs-on: ubuntu-latest
|
||||
build:
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
timeout-minutes: 130
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: api-build
|
||||
file: Dockerfile.multi
|
||||
image_name: librechat-dev-api
|
||||
- target: node
|
||||
file: Dockerfile
|
||||
image_name: librechat-dev
|
||||
|
||||
steps:
|
||||
- name: Sync notice
|
||||
run: echo "native pipeline is .hanzo/workflows/deploy.yml; GitHub is a mirror"
|
||||
# Check out the repository
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Set up QEMU
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
# Set up Docker Buildx
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
# Log in to GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Login to Docker Hub
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
# Prepare the environment
|
||||
- name: Prepare environment
|
||||
run: |
|
||||
cp .env.example .env
|
||||
|
||||
- name: Compute build metadata
|
||||
run: |
|
||||
echo "BUILD_COMMIT=${{ github.sha }}" >> $GITHUB_ENV
|
||||
echo "BUILD_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
|
||||
|
||||
# Build and push Docker images for each target
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.file }}
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:${{ github.sha }}
|
||||
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:latest
|
||||
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:${{ github.sha }}
|
||||
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
target: ${{ matrix.target }}
|
||||
build-args: |
|
||||
BUILD_COMMIT=${{ env.BUILD_COMMIT }}
|
||||
BUILD_BRANCH=${{ env.BUILD_BRANCH }}
|
||||
BUILD_DATE=${{ env.BUILD_DATE }}
|
||||
|
||||
@@ -1,14 +1,79 @@
|
||||
# Neutralized — the native deploy pipeline is .hanzo/workflows/deploy.yml
|
||||
# (Hanzo Git push -> in-cluster act_runner -> BuildKit builds ./Dockerfile ->
|
||||
# ghcr.io/hanzoai/chat:<sha> -> kubectl patch app/chat -> operator reconcile).
|
||||
# GitHub is a mirror; this workflow no longer builds, publishes, or deploys.
|
||||
name: "Docker Dev Staging Images Build (sync notice)"
|
||||
name: Docker Dev Staging Images Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
notice:
|
||||
runs-on: ubuntu-latest
|
||||
build:
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: api-build
|
||||
file: Dockerfile.multi
|
||||
image_name: lc-dev-staging-api
|
||||
- target: node
|
||||
file: Dockerfile
|
||||
image_name: lc-dev-staging
|
||||
|
||||
steps:
|
||||
- name: Sync notice
|
||||
run: echo "native pipeline is .hanzo/workflows/deploy.yml; GitHub is a mirror"
|
||||
# Check out the repository
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Set up QEMU
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
# Set up Docker Buildx
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
# Log in to GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Login to Docker Hub
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
# Prepare the environment
|
||||
- name: Prepare environment
|
||||
run: |
|
||||
cp .env.example .env
|
||||
|
||||
- name: Compute build metadata
|
||||
run: |
|
||||
echo "BUILD_COMMIT=${{ github.sha }}" >> $GITHUB_ENV
|
||||
echo "BUILD_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
|
||||
|
||||
# Build and push Docker images for each target
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.file }}
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:${{ github.sha }}
|
||||
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:latest
|
||||
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:${{ github.sha }}
|
||||
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
target: ${{ matrix.target }}
|
||||
build-args: |
|
||||
BUILD_COMMIT=${{ env.BUILD_COMMIT }}
|
||||
BUILD_BRANCH=${{ env.BUILD_BRANCH }}
|
||||
BUILD_DATE=${{ env.BUILD_DATE }}
|
||||
|
||||
@@ -1,14 +1,71 @@
|
||||
# Neutralized — the native deploy pipeline is .hanzo/workflows/deploy.yml
|
||||
# (Hanzo Git push -> in-cluster act_runner -> BuildKit builds ./Dockerfile ->
|
||||
# ghcr.io/hanzoai/chat:<sha> -> kubectl patch app/chat -> operator reconcile).
|
||||
# GitHub is a mirror; this workflow no longer builds, publishes, or deploys.
|
||||
name: "Docker Release (sync notice)"
|
||||
# Hanzo Chat — image build (amd64, self-hosted hanzoai pool).
|
||||
#
|
||||
# chat is a PUBLIC repo, so it cannot reuse the private hanzoai/.github
|
||||
# reusable workflow (GitHub blocks public->private workflow reuse).
|
||||
# This is therefore self-contained.
|
||||
#
|
||||
# Builds ghcr.io/hanzoai/chat on:
|
||||
# - push to main -> immutable sha-<sha7> tag
|
||||
# - v* tags -> semver image tag (e.g. v0.7.10 -> 0.7.10)
|
||||
# No :latest, no floating tags (semver-only policy). amd64 only
|
||||
# (DOKS is all amd64 — no arm64 runners).
|
||||
name: Docker Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
tags: ["v*"]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: docker-release-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
notice:
|
||||
runs-on: ubuntu-latest
|
||||
build-amd64:
|
||||
# hanzoai org pool — ARC routes by runnerScaleSetName, not labels.
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
steps:
|
||||
- name: Sync notice
|
||||
run: echo "native pipeline is .hanzo/workflows/deploy.yml; GitHub is a mirror"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver: docker-container
|
||||
driver-opts: network=host
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ghcr.io/hanzoai/chat
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=sha,prefix=sha-,format=short
|
||||
flavor: |
|
||||
latest=false
|
||||
|
||||
- name: Build and push amd64 image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=ghcr.io/hanzoai/chat-cache:amd64
|
||||
cache-to: type=registry,ref=ghcr.io/hanzoai/chat-cache:amd64,mode=max
|
||||
provenance: false
|
||||
|
||||
@@ -21,12 +21,9 @@ jobs:
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
env:
|
||||
CI: true
|
||||
# pnpm run frontend builds packages/api (rollup, ~5 GiB peak) + the client;
|
||||
# the default ~2 GiB heap OOMs. Match the review workflows' heap knob.
|
||||
NODE_OPTIONS: '--max-old-space-size=${{ secrets.NODE_MAX_OLD_SPACE_SIZE || 6144 }}'
|
||||
NODE_ENV: CI
|
||||
SEARCH: false
|
||||
MONGO_URI: mongodb://localhost:27017/chat-test
|
||||
MONGO_URI: mongodb://localhost:27017/librechat-test
|
||||
JWT_SECRET: e2e-test-jwt-secret
|
||||
JWT_REFRESH_SECRET: e2e-test-jwt-refresh-secret
|
||||
CREDS_KEY: e2e-test-creds-key-32chars00000000
|
||||
|
||||
@@ -74,7 +74,7 @@ jobs:
|
||||
run: |
|
||||
ssh -i ~/.ssh/deploy_key "$SSH_USER@$SSH_HOST" PR_NUM="$PR_NUM" bash <<'REMOTE'
|
||||
set -e
|
||||
TARGET="/opt/gitnexus/indexes/Chat-pr-$PR_NUM"
|
||||
TARGET="/opt/gitnexus/indexes/LibreChat-pr-$PR_NUM"
|
||||
if [ -d "$TARGET" ]; then
|
||||
echo "Removing $TARGET"
|
||||
rm -rf "$TARGET"
|
||||
|
||||
@@ -71,7 +71,7 @@ permissions:
|
||||
# cancel-in-progress so rapid pushes to the same ref coalesced but deploys
|
||||
# targeting different refs ran in parallel. That had a data race: the
|
||||
# prune-stale-indexes step computes its active_names up front, so if
|
||||
# deploy A is rsyncing /opt/gitnexus/indexes/Chat-pr-12580 while
|
||||
# deploy A is rsyncing /opt/gitnexus/indexes/LibreChat-pr-12580 while
|
||||
# deploy B (started slightly later with a different ref) prunes, B can
|
||||
# rm -rf a folder A is still uploading into.
|
||||
#
|
||||
@@ -85,7 +85,7 @@ concurrency:
|
||||
|
||||
env:
|
||||
GITNEXUS_VERSION: '1.5.3'
|
||||
IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/chat-gitnexus
|
||||
IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/librechat-gitnexus
|
||||
|
||||
jobs:
|
||||
# Rebuilds the long-lived image only when Dockerfile/entrypoint/extensions
|
||||
@@ -200,8 +200,8 @@ jobs:
|
||||
|
||||
// --- main and dev branches ---
|
||||
for (const [branch, name] of [
|
||||
['main', 'Chat'],
|
||||
['dev', 'Chat-dev'],
|
||||
['main', 'LibreChat'],
|
||||
['dev', 'LibreChat-dev'],
|
||||
]) {
|
||||
const artifactName = `gitnexus-index-${branch}`;
|
||||
const fresh = await latestArtifact(artifactName);
|
||||
@@ -260,11 +260,11 @@ jobs:
|
||||
|
||||
for (const { pr, artifactName, fresh } of keptPrs) {
|
||||
serve.push({
|
||||
name: `Chat-pr-${pr.number}`,
|
||||
name: `LibreChat-pr-${pr.number}`,
|
||||
artifactName,
|
||||
runId: fresh.workflow_run.id,
|
||||
});
|
||||
core.info(`PR #${pr.number}: run ${fresh.workflow_run.id} -> Chat-pr-${pr.number}`);
|
||||
core.info(`PR #${pr.number}: run ${fresh.workflow_run.id} -> LibreChat-pr-${pr.number}`);
|
||||
}
|
||||
if (evictedPrs.length) {
|
||||
core.info(
|
||||
@@ -305,7 +305,7 @@ jobs:
|
||||
--name "$artifact" \
|
||||
--dir "$target"; then
|
||||
case "$name" in
|
||||
Chat|Chat-dev)
|
||||
LibreChat|LibreChat-dev)
|
||||
echo "::error::Failed to download critical artifact $artifact"
|
||||
exit 1
|
||||
;;
|
||||
@@ -438,7 +438,7 @@ jobs:
|
||||
# is visible and the container isn't restarted with stale
|
||||
# or missing data. PR indexes are best-effort.
|
||||
case "$name" in
|
||||
Chat|Chat-dev)
|
||||
LibreChat|LibreChat-dev)
|
||||
echo "::error::rsync failed for critical index $name — aborting deploy"
|
||||
exit 1
|
||||
;;
|
||||
@@ -566,10 +566,10 @@ jobs:
|
||||
const matrix = JSON.parse(process.env.MATRIX || '[]');
|
||||
const triggerRunId = Number(process.env.TRIGGER_RUN_ID);
|
||||
const match = matrix.find(
|
||||
(m) => m.runId === triggerRunId && m.name.startsWith('Chat-pr-'),
|
||||
(m) => m.runId === triggerRunId && m.name.startsWith('LibreChat-pr-'),
|
||||
);
|
||||
if (match) {
|
||||
prNum = parseInt(match.name.replace('Chat-pr-', ''), 10);
|
||||
prNum = parseInt(match.name.replace('LibreChat-pr-', ''), 10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,7 +584,7 @@ jobs:
|
||||
`### GitNexus: ${ok ? '🚀 deployed' : '❌ deploy failed'}`,
|
||||
'',
|
||||
ok
|
||||
? `The \`Chat-pr-${prNum}\` index is now live on the MCP server.`
|
||||
? `The \`LibreChat-pr-${prNum}\` index is now live on the MCP server.`
|
||||
: `The deploy failed — the previous index (if any) continues to be served.`,
|
||||
`[Deploy run](${deployUrl})`,
|
||||
].join('\n');
|
||||
|
||||
@@ -30,9 +30,9 @@ jobs:
|
||||
|
||||
- name: Build Subchart Deps
|
||||
run: |
|
||||
cd helm/chat
|
||||
cd helm/librechat
|
||||
helm dependency build
|
||||
cd ../chat-rag-api
|
||||
cd ../librechat-rag-api
|
||||
helm dependency build
|
||||
|
||||
- name: Get Chart Version
|
||||
@@ -50,26 +50,26 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Run Helm OCI Charts Releaser
|
||||
# This is for the chat chart
|
||||
- name: Release Helm OCI Charts for chat
|
||||
# This is for the librechat chart
|
||||
- name: Release Helm OCI Charts for librechat
|
||||
uses: appany/helm-oci-chart-releaser@v0.5.0
|
||||
with:
|
||||
name: chat
|
||||
repository: ${{ github.actor }}/chat-chart
|
||||
name: librechat
|
||||
repository: ${{ github.actor }}/librechat-chart
|
||||
tag: ${{ steps.chart-version.outputs.CHART_VERSION }}
|
||||
path: helm/chat
|
||||
path: helm/librechat
|
||||
registry: ghcr.io
|
||||
registry_username: ${{ github.actor }}
|
||||
registry_password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# this is for the chat-rag-api chart
|
||||
- name: Release Helm OCI Charts for chat-rag-api
|
||||
# this is for the librechat-rag-api chart
|
||||
- name: Release Helm OCI Charts for librechat-rag-api
|
||||
uses: appany/helm-oci-chart-releaser@v0.5.0
|
||||
with:
|
||||
name: chat-rag-api
|
||||
repository: ${{ github.actor }}/chat-chart
|
||||
name: librechat-rag-api
|
||||
repository: ${{ github.actor }}/librechat-chart
|
||||
tag: ${{ steps.chart-version.outputs.CHART_VERSION }}
|
||||
path: helm/chat-rag-api
|
||||
path: helm/librechat-rag-api
|
||||
registry: ghcr.io
|
||||
registry_username: ${{ github.actor }}
|
||||
registry_password: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -119,31 +119,30 @@ jobs:
|
||||
echo "unused_keys=[]" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
# Post via github-script (Octokit + the built-in token) rather than the gh
|
||||
# CLI: gh is not installed on the self-hosted ARC runners, so `gh api` here
|
||||
# exits 127. The job already grants `pull-requests: write`.
|
||||
- name: Post verified comment on PR
|
||||
if: env.unused_keys != '[]'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const keys = JSON.parse(process.env.unused_keys || '[]').filter(Boolean);
|
||||
const list = keys.map((k) => `- [ ] \`${k}\``).join('\n');
|
||||
const body = [
|
||||
'### 🚨 Unused i18next Keys Detected',
|
||||
'',
|
||||
'The following translation keys are defined in `translation.json` but are **not used** in the codebase:',
|
||||
'',
|
||||
list,
|
||||
'',
|
||||
'⚠️ **Please remove these unused keys to keep the translation files clean.**',
|
||||
].join('\n');
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body,
|
||||
});
|
||||
run: |
|
||||
PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")
|
||||
|
||||
# Format the unused keys list as checkboxes for easy manual checking.
|
||||
FILTERED_KEYS=$(echo "$unused_keys" | jq -r '.[]' | grep -v '^\s*$' | sed 's/^/- [ ] `/;s/$/`/' )
|
||||
|
||||
COMMENT_BODY=$(cat <<EOF
|
||||
### 🚨 Unused i18next Keys Detected
|
||||
|
||||
The following translation keys are defined in \`translation.json\` but are **not used** in the codebase:
|
||||
|
||||
$FILTERED_KEYS
|
||||
|
||||
⚠️ **Please remove these unused keys to keep the translation files clean.**
|
||||
EOF
|
||||
)
|
||||
|
||||
gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
|
||||
-f body="$COMMENT_BODY" \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Fail workflow if unused keys found
|
||||
if: env.unused_keys != '[]'
|
||||
|
||||
@@ -1,14 +1,92 @@
|
||||
# Neutralized — the native deploy pipeline is .hanzo/workflows/deploy.yml
|
||||
# (Hanzo Git push -> in-cluster act_runner -> BuildKit builds ./Dockerfile ->
|
||||
# ghcr.io/hanzoai/chat:<sha> -> kubectl patch app/chat -> operator reconcile).
|
||||
# GitHub is a mirror; this workflow no longer builds, publishes, or deploys.
|
||||
name: "Docker Compose Build Latest Main Image Tag (Manual Dispatch) (sync notice)"
|
||||
name: Docker Compose Build Latest Main Image Tag (Manual Dispatch)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
notice:
|
||||
runs-on: ubuntu-latest
|
||||
build:
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: api-build
|
||||
file: Dockerfile.multi
|
||||
image_name: librechat-api
|
||||
- target: node
|
||||
file: Dockerfile
|
||||
image_name: librechat
|
||||
|
||||
steps:
|
||||
- name: Sync notice
|
||||
run: echo "native pipeline is .hanzo/workflows/deploy.yml; GitHub is a mirror"
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: main
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Fetch tags and set the latest tag
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git fetch --tags --force
|
||||
LATEST_TAG=$(git tag --list 'v[0-9]*' --sort=-v:refname | grep -E '^v[0-9]+[.][0-9]+[.][0-9]+$' | head -n 1)
|
||||
if [ -z "$LATEST_TAG" ]; then
|
||||
echo "::error::No stable v<semver> tag found"
|
||||
exit 1
|
||||
fi
|
||||
printf 'LATEST_TAG=%s\n' "$LATEST_TAG" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Compute build metadata
|
||||
run: |
|
||||
printf 'BUILD_COMMIT=%s\n' "$(git rev-parse HEAD)" >> "$GITHUB_ENV"
|
||||
printf 'BUILD_BRANCH=main\n' >> "$GITHUB_ENV"
|
||||
printf 'BUILD_DATE=%s\n' "$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> "$GITHUB_ENV"
|
||||
|
||||
# Set up QEMU
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
# Set up Docker Buildx
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
# Log in to GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Login to Docker Hub
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
# Prepare the environment
|
||||
- name: Prepare environment
|
||||
run: |
|
||||
cp .env.example .env
|
||||
|
||||
# Build and push Docker images for each target
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.file }}
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:${{ env.LATEST_TAG }}
|
||||
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:latest
|
||||
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:${{ env.LATEST_TAG }}
|
||||
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
target: ${{ matrix.target }}
|
||||
build-args: |
|
||||
BUILD_COMMIT=${{ env.BUILD_COMMIT }}
|
||||
BUILD_BRANCH=${{ env.BUILD_BRANCH }}
|
||||
BUILD_DATE=${{ env.BUILD_DATE }}
|
||||
|
||||
@@ -16,6 +16,6 @@ jobs:
|
||||
service: chat
|
||||
image: ghcr.io/hanzoai/chat
|
||||
port: "3080"
|
||||
health-path: /health
|
||||
health-path: /api/health
|
||||
e2e-dir: e2e
|
||||
secrets: inherit
|
||||
|
||||
@@ -39,14 +39,14 @@ jobs:
|
||||
env:
|
||||
BASE_REF: refs/remotes/origin/main
|
||||
BACKFILL_FROM_VERSION: 1.9.0
|
||||
CHART_PATH: helm/chat/Chart.yaml
|
||||
CHART_PATH: helm/librechat/Chart.yaml
|
||||
DEFAULT_BRANCH: main
|
||||
DISPATCH_WORKFLOW: helmcharts.yml
|
||||
GITHUB_SERVER_URL: ${{ github.server_url }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
RELEASE_EXISTING_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.release_existing_tag || '' }}
|
||||
REPO_DIR: /tmp/chat-sync
|
||||
REPO_DIR: /tmp/librechat-sync
|
||||
TAG_PREFIX: chart-
|
||||
steps:
|
||||
- name: Fetch main and tags
|
||||
|
||||
@@ -1,14 +1,116 @@
|
||||
# Neutralized — the native deploy pipeline is .hanzo/workflows/deploy.yml
|
||||
# (Hanzo Git push -> in-cluster act_runner -> BuildKit builds ./Dockerfile ->
|
||||
# ghcr.io/hanzoai/chat:<sha> -> kubectl patch app/chat -> operator reconcile).
|
||||
# GitHub is a mirror; this workflow no longer builds, publishes, or deploys.
|
||||
name: "Docker Images Build on Tag (sync notice)"
|
||||
name: Docker Images Build on Tag
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
notice:
|
||||
runs-on: ubuntu-latest
|
||||
build:
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: api-build
|
||||
file: Dockerfile.multi
|
||||
image_name: librechat-api
|
||||
- target: node
|
||||
file: Dockerfile
|
||||
image_name: librechat
|
||||
|
||||
steps:
|
||||
- name: Sync notice
|
||||
run: echo "native pipeline is .hanzo/workflows/deploy.yml; GitHub is a mirror"
|
||||
# Check out the repository
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Validate release tag
|
||||
id: release-tag
|
||||
env:
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TAG_REGEX='^v[0-9]+[.][0-9]+[.][0-9]+(-rc[0-9]+)?$'
|
||||
STABLE_TAG_REGEX='^v[0-9]+[.][0-9]+[.][0-9]+$'
|
||||
if [[ ! "$REF_NAME" =~ $TAG_REGEX ]]; then
|
||||
echo "::error::Docker release tags must use v<semver> or v<semver>-rcN, for example v0.8.5 or v0.8.5-rc1"
|
||||
exit 1
|
||||
fi
|
||||
printf 'image_tag=%s\n' "$REF_NAME" >> "$GITHUB_OUTPUT"
|
||||
if [[ "$REF_NAME" =~ $STABLE_TAG_REGEX ]]; then
|
||||
echo "is_stable=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "is_stable=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Set up QEMU
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
# Set up Docker Buildx
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
# Log in to GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Login to Docker Hub
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
# Prepare the environment
|
||||
- name: Prepare environment
|
||||
run: |
|
||||
cp .env.example .env
|
||||
|
||||
- name: Compute build metadata
|
||||
run: |
|
||||
echo "BUILD_COMMIT=${{ github.sha }}" >> $GITHUB_ENV
|
||||
echo "BUILD_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
|
||||
|
||||
- name: Resolve image tags
|
||||
id: image-tags
|
||||
env:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
IMAGE_NAME: ${{ matrix.image_name }}
|
||||
IMAGE_TAG: ${{ steps.release-tag.outputs.image_tag }}
|
||||
IS_STABLE: ${{ steps.release-tag.outputs.is_stable }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
{
|
||||
echo 'tags<<EOF'
|
||||
printf 'ghcr.io/%s/%s:%s\n' "$GITHUB_REPOSITORY_OWNER" "$IMAGE_NAME" "$IMAGE_TAG"
|
||||
printf '%s/%s:%s\n' "$DOCKERHUB_USERNAME" "$IMAGE_NAME" "$IMAGE_TAG"
|
||||
if [ "$IS_STABLE" = "true" ]; then
|
||||
printf 'ghcr.io/%s/%s:latest\n' "$GITHUB_REPOSITORY_OWNER" "$IMAGE_NAME"
|
||||
printf '%s/%s:latest\n' "$DOCKERHUB_USERNAME" "$IMAGE_NAME"
|
||||
fi
|
||||
echo 'EOF'
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Build and push Docker images for each target
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.file }}
|
||||
push: true
|
||||
tags: ${{ steps.image-tags.outputs.tags }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
target: ${{ matrix.target }}
|
||||
build-args: |
|
||||
BUILD_COMMIT=${{ env.BUILD_COMMIT }}
|
||||
BUILD_BRANCH=${{ env.BUILD_BRANCH }}
|
||||
BUILD_DATE=${{ env.BUILD_DATE }}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
name: LiteLLM Linting
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
timeout-minutes: 5
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Install Poetry
|
||||
uses: snok/install-poetry@v1
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install openai==1.81.0
|
||||
poetry install --with dev
|
||||
pip install openai==1.81.0
|
||||
|
||||
|
||||
|
||||
- name: Run Black formatting
|
||||
run: |
|
||||
cd litellm
|
||||
poetry run black .
|
||||
cd ..
|
||||
|
||||
- name: Run Ruff linting
|
||||
run: |
|
||||
cd litellm
|
||||
poetry run ruff check .
|
||||
cd ..
|
||||
|
||||
- name: Run MyPy type checking
|
||||
run: |
|
||||
cd litellm
|
||||
poetry run mypy . --ignore-missing-imports
|
||||
cd ..
|
||||
|
||||
- name: Check for circular imports
|
||||
run: |
|
||||
cd litellm
|
||||
poetry run python ../tests/documentation_tests/test_circular_imports.py
|
||||
cd ..
|
||||
|
||||
- name: Check import safety
|
||||
run: |
|
||||
poetry run python -c "from litellm import *" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1)
|
||||
@@ -10,12 +10,6 @@ jobs:
|
||||
test:
|
||||
runs-on: hanzo-build-linux-amd64
|
||||
|
||||
# The packages/api rollup build peaks ~5 GiB RSS and OOMs at Node's default
|
||||
# ~2 GiB old-space heap. Match the heap the review workflows already use
|
||||
# (well under the 8 GiB runner limit). One knob, same expression everywhere.
|
||||
env:
|
||||
NODE_OPTIONS: '--max-old-space-size=${{ secrets.NODE_MAX_OLD_SPACE_SIZE || 6144 }}'
|
||||
|
||||
services:
|
||||
mongodb:
|
||||
image: mongo:7
|
||||
@@ -68,19 +62,9 @@ jobs:
|
||||
run: pnpm run test:api
|
||||
env:
|
||||
NODE_ENV: test
|
||||
MONGO_URI: mongodb://localhost:27017/chat-test
|
||||
MONGO_URI: mongodb://localhost:27017/librechat-test
|
||||
MEILI_HOST: http://localhost:7700
|
||||
MEILI_MASTER_KEY: test_master_key
|
||||
|
||||
# Gate against tests-without-implementation drift in the MCP connection/
|
||||
# transport layer (proxy, response-size caps, WS SSRF, allowedAddresses).
|
||||
# These suites live in packages/api and were never run by this workflow —
|
||||
# which is how the connection.ts port drifted from its byte-identical tests.
|
||||
# A future half-port now fails here loudly.
|
||||
- name: Run MCP connection/transport tests
|
||||
run: cd packages/api && pnpm run test:transport
|
||||
env:
|
||||
NODE_ENV: test
|
||||
|
||||
- name: Run client tests
|
||||
run: pnpm run test:client
|
||||
@@ -117,52 +117,52 @@ jobs:
|
||||
extract_deps_from_code "packages/client" packages_client_used_code.txt
|
||||
extract_deps_from_code "packages/api" packages_api_used_code.txt
|
||||
|
||||
- name: Get @hanzochat/client dependencies
|
||||
id: get-chat-client-deps
|
||||
- name: Get @librechat/client dependencies
|
||||
id: get-librechat-client-deps
|
||||
run: |
|
||||
if [[ -f "packages/client/package.json" ]]; then
|
||||
# Get all dependencies from @hanzochat/client (dependencies, devDependencies, and peerDependencies)
|
||||
# Get all dependencies from @librechat/client (dependencies, devDependencies, and peerDependencies)
|
||||
DEPS=$(jq -r '.dependencies // {} | keys[]' packages/client/package.json 2>/dev/null || echo "")
|
||||
DEV_DEPS=$(jq -r '.devDependencies // {} | keys[]' packages/client/package.json 2>/dev/null || echo "")
|
||||
PEER_DEPS=$(jq -r '.peerDependencies // {} | keys[]' packages/client/package.json 2>/dev/null || echo "")
|
||||
|
||||
# Combine all dependencies
|
||||
echo "$DEPS" > chat_client_deps.txt
|
||||
echo "$DEV_DEPS" >> chat_client_deps.txt
|
||||
echo "$PEER_DEPS" >> chat_client_deps.txt
|
||||
echo "$DEPS" > librechat_client_deps.txt
|
||||
echo "$DEV_DEPS" >> librechat_client_deps.txt
|
||||
echo "$PEER_DEPS" >> librechat_client_deps.txt
|
||||
|
||||
# Also include dependencies that are imported in packages/client
|
||||
cat packages_client_used_code.txt >> chat_client_deps.txt
|
||||
cat packages_client_used_code.txt >> librechat_client_deps.txt
|
||||
|
||||
# Remove empty lines and sort
|
||||
grep -v '^$' chat_client_deps.txt | sort -u > temp_deps.txt
|
||||
mv temp_deps.txt chat_client_deps.txt
|
||||
grep -v '^$' librechat_client_deps.txt | sort -u > temp_deps.txt
|
||||
mv temp_deps.txt librechat_client_deps.txt
|
||||
else
|
||||
touch chat_client_deps.txt
|
||||
touch librechat_client_deps.txt
|
||||
fi
|
||||
|
||||
- name: Get @hanzochat/api dependencies
|
||||
id: get-chat-api-deps
|
||||
- name: Get @librechat/api dependencies
|
||||
id: get-librechat-api-deps
|
||||
run: |
|
||||
if [[ -f "packages/api/package.json" ]]; then
|
||||
# Get all dependencies from @hanzochat/api (dependencies, devDependencies, and peerDependencies)
|
||||
# Get all dependencies from @librechat/api (dependencies, devDependencies, and peerDependencies)
|
||||
DEPS=$(jq -r '.dependencies // {} | keys[]' packages/api/package.json 2>/dev/null || echo "")
|
||||
DEV_DEPS=$(jq -r '.devDependencies // {} | keys[]' packages/api/package.json 2>/dev/null || echo "")
|
||||
PEER_DEPS=$(jq -r '.peerDependencies // {} | keys[]' packages/api/package.json 2>/dev/null || echo "")
|
||||
|
||||
# Combine all dependencies
|
||||
echo "$DEPS" > chat_api_deps.txt
|
||||
echo "$DEV_DEPS" >> chat_api_deps.txt
|
||||
echo "$PEER_DEPS" >> chat_api_deps.txt
|
||||
echo "$DEPS" > librechat_api_deps.txt
|
||||
echo "$DEV_DEPS" >> librechat_api_deps.txt
|
||||
echo "$PEER_DEPS" >> librechat_api_deps.txt
|
||||
|
||||
# Also include dependencies that are imported in packages/api
|
||||
cat packages_api_used_code.txt >> chat_api_deps.txt
|
||||
cat packages_api_used_code.txt >> librechat_api_deps.txt
|
||||
|
||||
# Remove empty lines and sort
|
||||
grep -v '^$' chat_api_deps.txt | sort -u > temp_deps.txt
|
||||
mv temp_deps.txt chat_api_deps.txt
|
||||
grep -v '^$' librechat_api_deps.txt | sort -u > temp_deps.txt
|
||||
mv temp_deps.txt librechat_api_deps.txt
|
||||
else
|
||||
touch chat_api_deps.txt
|
||||
touch librechat_api_deps.txt
|
||||
fi
|
||||
|
||||
- name: Extract Workspace Dependencies
|
||||
@@ -173,14 +173,14 @@ jobs:
|
||||
local package_json=$1
|
||||
local output_file=$2
|
||||
|
||||
# Get all workspace dependencies (starting with @hanzochat/)
|
||||
# Get all workspace dependencies (starting with @librechat/)
|
||||
if [[ -f "$package_json" ]]; then
|
||||
local workspace_deps=$(jq -r '.dependencies // {} | to_entries[] | select(.key | startswith("@hanzochat/")) | .key' "$package_json" 2>/dev/null || echo "")
|
||||
local workspace_deps=$(jq -r '.dependencies // {} | to_entries[] | select(.key | startswith("@librechat/")) | .key' "$package_json" 2>/dev/null || echo "")
|
||||
|
||||
# For each workspace dependency, get its dependencies
|
||||
for dep in $workspace_deps; do
|
||||
# Convert @hanzochat/api to packages/api
|
||||
local workspace_path=$(echo "$dep" | sed 's/@chat\//packages\//')
|
||||
# Convert @librechat/api to packages/api
|
||||
local workspace_path=$(echo "$dep" | sed 's/@librechat\//packages\//')
|
||||
local workspace_package_json="${workspace_path}/package.json"
|
||||
|
||||
if [[ -f "$workspace_package_json" ]]; then
|
||||
@@ -223,8 +223,8 @@ jobs:
|
||||
chmod -R 755 client
|
||||
cd client
|
||||
UNUSED=$(depcheck --json | jq -r '.dependencies | join("\n")' || echo "")
|
||||
# Exclude dependencies used in scripts, code, workspace packages, and @hanzochat/client imports
|
||||
UNUSED=$(comm -23 <(echo "$UNUSED" | sort) <(cat ../client_used_deps.txt ../client_used_code.txt ../client_workspace_deps.txt ../packages_client_used_code.txt ../chat_client_deps.txt 2>/dev/null | sort -u) || echo "")
|
||||
# Exclude dependencies used in scripts, code, workspace packages, and @librechat/client imports
|
||||
UNUSED=$(comm -23 <(echo "$UNUSED" | sort) <(cat ../client_used_deps.txt ../client_used_code.txt ../client_workspace_deps.txt ../packages_client_used_code.txt ../librechat_client_deps.txt 2>/dev/null | sort -u) || echo "")
|
||||
# Filter out false positives
|
||||
UNUSED=$(echo "$UNUSED" | grep -v "^micromark-extension-llm-math$" || echo "")
|
||||
echo "CLIENT_UNUSED<<EOF" >> $GITHUB_ENV
|
||||
@@ -240,43 +240,43 @@ jobs:
|
||||
chmod -R 755 api
|
||||
cd api
|
||||
UNUSED=$(depcheck --json | jq -r '.dependencies | join("\n")' || echo "")
|
||||
# Exclude dependencies used in scripts, code, workspace packages, and @hanzochat/api imports
|
||||
UNUSED=$(comm -23 <(echo "$UNUSED" | sort) <(cat ../api_used_deps.txt ../api_used_code.txt ../api_workspace_deps.txt ../packages_api_used_code.txt ../chat_api_deps.txt 2>/dev/null | sort -u) || echo "")
|
||||
# Exclude dependencies used in scripts, code, workspace packages, and @librechat/api imports
|
||||
UNUSED=$(comm -23 <(echo "$UNUSED" | sort) <(cat ../api_used_deps.txt ../api_used_code.txt ../api_workspace_deps.txt ../packages_api_used_code.txt ../librechat_api_deps.txt 2>/dev/null | sort -u) || echo "")
|
||||
echo "API_UNUSED<<EOF" >> $GITHUB_ENV
|
||||
echo "$UNUSED" >> $GITHUB_ENV
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
cd ..
|
||||
fi
|
||||
|
||||
# Post via github-script (Octokit + the built-in token) rather than the gh
|
||||
# CLI: gh is not installed on the self-hosted ARC runners, so `gh api` here
|
||||
# exits 127. The job already grants `pull-requests: write`.
|
||||
- name: Post comment on PR if unused dependencies are found
|
||||
if: env.ROOT_UNUSED != '' || env.CLIENT_UNUSED != '' || env.API_UNUSED != ''
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const section = (title, val) => {
|
||||
const items = (val || '').split('\n').map((s) => s.trim()).filter(Boolean);
|
||||
if (!items.length) return '';
|
||||
return `#### 📂 ${title}\n\n${items.map((i) => `- \`${i}\``).join('\n')}\n`;
|
||||
};
|
||||
const body = [
|
||||
'### 🚨 Unused NPM Packages Detected',
|
||||
'',
|
||||
'The following **unused dependencies** were found:',
|
||||
'',
|
||||
section('Root `package.json`', process.env.ROOT_UNUSED),
|
||||
section('Client `client/package.json`', process.env.CLIENT_UNUSED),
|
||||
section('API `api/package.json`', process.env.API_UNUSED),
|
||||
'⚠️ **Please remove these unused dependencies to keep your project clean.**',
|
||||
].filter(Boolean).join('\n');
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body,
|
||||
});
|
||||
run: |
|
||||
PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")
|
||||
|
||||
ROOT_LIST=$(echo "$ROOT_UNUSED" | awk '{print "- `" $0 "`"}')
|
||||
CLIENT_LIST=$(echo "$CLIENT_UNUSED" | awk '{print "- `" $0 "`"}')
|
||||
API_LIST=$(echo "$API_UNUSED" | awk '{print "- `" $0 "`"}')
|
||||
|
||||
COMMENT_BODY=$(cat <<EOF
|
||||
### 🚨 Unused NPM Packages Detected
|
||||
|
||||
The following **unused dependencies** were found:
|
||||
|
||||
$(if [[ ! -z "$ROOT_UNUSED" ]]; then echo "#### 📂 Root \`package.json\`"; echo ""; echo "$ROOT_LIST"; echo ""; fi)
|
||||
|
||||
$(if [[ ! -z "$CLIENT_UNUSED" ]]; then echo "#### 📂 Client \`client/package.json\`"; echo ""; echo "$CLIENT_LIST"; echo ""; fi)
|
||||
|
||||
$(if [[ ! -z "$API_UNUSED" ]]; then echo "#### 📂 API \`api/package.json\`"; echo ""; echo "$API_LIST"; echo ""; fi)
|
||||
|
||||
⚠️ **Please remove these unused dependencies to keep your project clean.**
|
||||
EOF
|
||||
)
|
||||
|
||||
gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
|
||||
-f body="$COMMENT_BODY" \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Fail workflow if unused dependencies found
|
||||
if: env.ROOT_UNUSED != '' || env.CLIENT_UNUSED != '' || env.API_UNUSED != ''
|
||||
|
||||
+3
-3
@@ -121,12 +121,12 @@ docker-compose.override.yml
|
||||
dump.rdb
|
||||
helm/**/.values.yaml
|
||||
helm/**/charts/
|
||||
helm/chat/Chart.lock
|
||||
helm/librechat/Chart.lock
|
||||
hive-mind-prompt-*.txt
|
||||
junit.xml
|
||||
lib-cov
|
||||
chat.yaml
|
||||
chat.yml
|
||||
librechat.yaml
|
||||
librechat.yml
|
||||
logs
|
||||
meili_data*
|
||||
meili_data/
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
name: deploy
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: hanzo-linux-amd64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build + push image
|
||||
run: |
|
||||
SHA="${GITHUB_SHA::8}"
|
||||
buildctl-daemonless.sh build --frontend=dockerfile.v0 \
|
||||
--opt context="${{ github.server_url }}/${{ github.repository }}.git#${GITHUB_SHA}" \
|
||||
--opt filename=Dockerfile --opt platform=linux/amd64 \
|
||||
--secret id=GIT_AUTH_TOKEN,env=GIT_AUTH_TOKEN \
|
||||
--output "type=image,name=ghcr.io/hanzoai/chat:${SHA},push=true" --progress=plain
|
||||
env:
|
||||
GIT_AUTH_TOKEN: ${{ secrets.GIT_CLONE_TOKEN }}
|
||||
- name: Deploy — declare tag to operator
|
||||
run: |
|
||||
for app in chat; do
|
||||
kubectl -n hanzo patch app "$app" --type=merge -p "{\"spec\":{\"image\":{\"repository\":\"ghcr.io/hanzoai/chat\",\"tag\":\"${GITHUB_SHA::8}\"}}}"
|
||||
done
|
||||
+166
-166
@@ -11,41 +11,41 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
### ✨ New Features
|
||||
|
||||
- ✨ feat: implement search parameter updates by **@mawburn** in [#7151](https://github.com/danny-avila/Chat/pull/7151)
|
||||
- 🎏 feat: Add MCP support for Streamable HTTP Transport by **@benverhees** in [#7353](https://github.com/danny-avila/Chat/pull/7353)
|
||||
- 🔒 feat: Add Content Security Policy using Helmet middleware by **@rubentalstra** in [#7377](https://github.com/danny-avila/Chat/pull/7377)
|
||||
- ✨ feat: Add Normalization for MCP Server Names by **@danny-avila** in [#7421](https://github.com/danny-avila/Chat/pull/7421)
|
||||
- 📊 feat: Improve Helm Chart by **@hofq** in [#3638](https://github.com/danny-avila/Chat/pull/3638)
|
||||
- 🦾 feat: Claude-4 Support by **@danny-avila** in [#7509](https://github.com/danny-avila/Chat/pull/7509)
|
||||
- 🪨 feat: Bedrock Support for Claude-4 Reasoning by **@danny-avila** in [#7517](https://github.com/danny-avila/Chat/pull/7517)
|
||||
- ✨ feat: implement search parameter updates by **@mawburn** in [#7151](https://github.com/danny-avila/LibreChat/pull/7151)
|
||||
- 🎏 feat: Add MCP support for Streamable HTTP Transport by **@benverhees** in [#7353](https://github.com/danny-avila/LibreChat/pull/7353)
|
||||
- 🔒 feat: Add Content Security Policy using Helmet middleware by **@rubentalstra** in [#7377](https://github.com/danny-avila/LibreChat/pull/7377)
|
||||
- ✨ feat: Add Normalization for MCP Server Names by **@danny-avila** in [#7421](https://github.com/danny-avila/LibreChat/pull/7421)
|
||||
- 📊 feat: Improve Helm Chart by **@hofq** in [#3638](https://github.com/danny-avila/LibreChat/pull/3638)
|
||||
- 🦾 feat: Claude-4 Support by **@danny-avila** in [#7509](https://github.com/danny-avila/LibreChat/pull/7509)
|
||||
- 🪨 feat: Bedrock Support for Claude-4 Reasoning by **@danny-avila** in [#7517](https://github.com/danny-avila/LibreChat/pull/7517)
|
||||
|
||||
### 🌍 Internationalization
|
||||
|
||||
- 🌍 i18n: Add `Danish` and `Czech` and `Catalan` localization support by **@rubentalstra** in [#7373](https://github.com/danny-avila/Chat/pull/7373)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#7375](https://github.com/danny-avila/Chat/pull/7375)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#7468](https://github.com/danny-avila/Chat/pull/7468)
|
||||
- 🌍 i18n: Add `Danish` and `Czech` and `Catalan` localization support by **@rubentalstra** in [#7373](https://github.com/danny-avila/LibreChat/pull/7373)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#7375](https://github.com/danny-avila/LibreChat/pull/7375)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#7468](https://github.com/danny-avila/LibreChat/pull/7468)
|
||||
|
||||
### 🔧 Fixes
|
||||
|
||||
- 💬 fix: update aria-label for accessibility in ConvoLink component by **@berry-13** in [#7320](https://github.com/danny-avila/Chat/pull/7320)
|
||||
- 🔑 fix: use `apiKey` instead of `openAIApiKey` in OpenAI-like Config by **@danny-avila** in [#7337](https://github.com/danny-avila/Chat/pull/7337)
|
||||
- 🔄 fix: update navigation logic in `useFocusChatEffect` to ensure correct search parameters are used by **@mawburn** in [#7340](https://github.com/danny-avila/Chat/pull/7340)
|
||||
- 🔄 fix: Improve MCP Connection Cleanup by **@danny-avila** in [#7400](https://github.com/danny-avila/Chat/pull/7400)
|
||||
- 🛡️ fix: Preset and Validation Logic for URL Query Params by **@danny-avila** in [#7407](https://github.com/danny-avila/Chat/pull/7407)
|
||||
- 🌘 fix: artifact of preview text is illegible in dark mode by **@nhtruong** in [#7405](https://github.com/danny-avila/Chat/pull/7405)
|
||||
- 🛡️ fix: Temporarily Remove CSP until Configurable by **@danny-avila** in [#7419](https://github.com/danny-avila/Chat/pull/7419)
|
||||
- 💽 fix: Exclude index page `/` from static cache settings by **@sbruel** in [#7382](https://github.com/danny-avila/Chat/pull/7382)
|
||||
- 💬 fix: update aria-label for accessibility in ConvoLink component by **@berry-13** in [#7320](https://github.com/danny-avila/LibreChat/pull/7320)
|
||||
- 🔑 fix: use `apiKey` instead of `openAIApiKey` in OpenAI-like Config by **@danny-avila** in [#7337](https://github.com/danny-avila/LibreChat/pull/7337)
|
||||
- 🔄 fix: update navigation logic in `useFocusChatEffect` to ensure correct search parameters are used by **@mawburn** in [#7340](https://github.com/danny-avila/LibreChat/pull/7340)
|
||||
- 🔄 fix: Improve MCP Connection Cleanup by **@danny-avila** in [#7400](https://github.com/danny-avila/LibreChat/pull/7400)
|
||||
- 🛡️ fix: Preset and Validation Logic for URL Query Params by **@danny-avila** in [#7407](https://github.com/danny-avila/LibreChat/pull/7407)
|
||||
- 🌘 fix: artifact of preview text is illegible in dark mode by **@nhtruong** in [#7405](https://github.com/danny-avila/LibreChat/pull/7405)
|
||||
- 🛡️ fix: Temporarily Remove CSP until Configurable by **@danny-avila** in [#7419](https://github.com/danny-avila/LibreChat/pull/7419)
|
||||
- 💽 fix: Exclude index page `/` from static cache settings by **@sbruel** in [#7382](https://github.com/danny-avila/LibreChat/pull/7382)
|
||||
|
||||
### ⚙️ Other Changes
|
||||
|
||||
- 📜 docs: CHANGELOG for release v0.7.8 by **@github-actions[bot]** in [#7290](https://github.com/danny-avila/Chat/pull/7290)
|
||||
- 📦 chore: Update API Package Dependencies by **@danny-avila** in [#7359](https://github.com/danny-avila/Chat/pull/7359)
|
||||
- 📜 docs: Unreleased Changelog by **@github-actions[bot]** in [#7321](https://github.com/danny-avila/Chat/pull/7321)
|
||||
- 📜 docs: Unreleased Changelog by **@github-actions[bot]** in [#7434](https://github.com/danny-avila/Chat/pull/7434)
|
||||
- 🛡️ chore: `multer` v2.0.0 for CVE-2025-47935 and CVE-2025-47944 by **@danny-avila** in [#7454](https://github.com/danny-avila/Chat/pull/7454)
|
||||
- 📂 refactor: Improve `FileAttachment` & File Form Deletion by **@danny-avila** in [#7471](https://github.com/danny-avila/Chat/pull/7471)
|
||||
- 📊 chore: Remove Old Helm Chart by **@hofq** in [#7512](https://github.com/danny-avila/Chat/pull/7512)
|
||||
- 🪖 chore: bump helm app version to v0.7.8 by **@austin-barrington** in [#7524](https://github.com/danny-avila/Chat/pull/7524)
|
||||
- 📜 docs: CHANGELOG for release v0.7.8 by **@github-actions[bot]** in [#7290](https://github.com/danny-avila/LibreChat/pull/7290)
|
||||
- 📦 chore: Update API Package Dependencies by **@danny-avila** in [#7359](https://github.com/danny-avila/LibreChat/pull/7359)
|
||||
- 📜 docs: Unreleased Changelog by **@github-actions[bot]** in [#7321](https://github.com/danny-avila/LibreChat/pull/7321)
|
||||
- 📜 docs: Unreleased Changelog by **@github-actions[bot]** in [#7434](https://github.com/danny-avila/LibreChat/pull/7434)
|
||||
- 🛡️ chore: `multer` v2.0.0 for CVE-2025-47935 and CVE-2025-47944 by **@danny-avila** in [#7454](https://github.com/danny-avila/LibreChat/pull/7454)
|
||||
- 📂 refactor: Improve `FileAttachment` & File Form Deletion by **@danny-avila** in [#7471](https://github.com/danny-avila/LibreChat/pull/7471)
|
||||
- 📊 chore: Remove Old Helm Chart by **@hofq** in [#7512](https://github.com/danny-avila/LibreChat/pull/7512)
|
||||
- 🪖 chore: bump helm app version to v0.7.8 by **@austin-barrington** in [#7524](https://github.com/danny-avila/LibreChat/pull/7524)
|
||||
|
||||
|
||||
|
||||
@@ -56,38 +56,38 @@ Changes from v0.7.8-rc1 to v0.7.8.
|
||||
|
||||
### ✨ New Features
|
||||
|
||||
- ✨ feat: Enhance form submission for touch screens by **@berry-13** in [#7198](https://github.com/danny-avila/Chat/pull/7198)
|
||||
- 🔍 feat: Additional Tavily API Tool Parameters by **@glowforge-opensource** in [#7232](https://github.com/danny-avila/Chat/pull/7232)
|
||||
- 🐋 feat: Add python to Dockerfile for increased MCP compatibility by **@technicalpickles** in [#7270](https://github.com/danny-avila/Chat/pull/7270)
|
||||
- ✨ feat: Enhance form submission for touch screens by **@berry-13** in [#7198](https://github.com/danny-avila/LibreChat/pull/7198)
|
||||
- 🔍 feat: Additional Tavily API Tool Parameters by **@glowforge-opensource** in [#7232](https://github.com/danny-avila/LibreChat/pull/7232)
|
||||
- 🐋 feat: Add python to Dockerfile for increased MCP compatibility by **@technicalpickles** in [#7270](https://github.com/danny-avila/LibreChat/pull/7270)
|
||||
|
||||
### 🔧 Fixes
|
||||
|
||||
- 🔧 fix: Google Gemma Support & OpenAI Reasoning Instructions by **@danny-avila** in [#7196](https://github.com/danny-avila/Chat/pull/7196)
|
||||
- 🛠️ fix: Conversation Navigation State by **@danny-avila** in [#7210](https://github.com/danny-avila/Chat/pull/7210)
|
||||
- 🔄 fix: o-Series Model Regex for System Messages by **@danny-avila** in [#7245](https://github.com/danny-avila/Chat/pull/7245)
|
||||
- 🔖 fix: Custom Headers for Initial MCP SSE Connection by **@danny-avila** in [#7246](https://github.com/danny-avila/Chat/pull/7246)
|
||||
- 🛡️ fix: Deep Clone `MCPOptions` for User MCP Connections by **@danny-avila** in [#7247](https://github.com/danny-avila/Chat/pull/7247)
|
||||
- 🔄 fix: URL Param Race Condition and File Draft Persistence by **@danny-avila** in [#7257](https://github.com/danny-avila/Chat/pull/7257)
|
||||
- 🔄 fix: Assistants Endpoint & Minor Issues by **@danny-avila** in [#7274](https://github.com/danny-avila/Chat/pull/7274)
|
||||
- 🔄 fix: Ollama Think Tag Edge Case with Tools by **@danny-avila** in [#7275](https://github.com/danny-avila/Chat/pull/7275)
|
||||
- 🔧 fix: Google Gemma Support & OpenAI Reasoning Instructions by **@danny-avila** in [#7196](https://github.com/danny-avila/LibreChat/pull/7196)
|
||||
- 🛠️ fix: Conversation Navigation State by **@danny-avila** in [#7210](https://github.com/danny-avila/LibreChat/pull/7210)
|
||||
- 🔄 fix: o-Series Model Regex for System Messages by **@danny-avila** in [#7245](https://github.com/danny-avila/LibreChat/pull/7245)
|
||||
- 🔖 fix: Custom Headers for Initial MCP SSE Connection by **@danny-avila** in [#7246](https://github.com/danny-avila/LibreChat/pull/7246)
|
||||
- 🛡️ fix: Deep Clone `MCPOptions` for User MCP Connections by **@danny-avila** in [#7247](https://github.com/danny-avila/LibreChat/pull/7247)
|
||||
- 🔄 fix: URL Param Race Condition and File Draft Persistence by **@danny-avila** in [#7257](https://github.com/danny-avila/LibreChat/pull/7257)
|
||||
- 🔄 fix: Assistants Endpoint & Minor Issues by **@danny-avila** in [#7274](https://github.com/danny-avila/LibreChat/pull/7274)
|
||||
- 🔄 fix: Ollama Think Tag Edge Case with Tools by **@danny-avila** in [#7275](https://github.com/danny-avila/LibreChat/pull/7275)
|
||||
|
||||
### ⚙️ Other Changes
|
||||
|
||||
- 📜 docs: CHANGELOG for release v0.7.8-rc1 by **@github-actions[bot]** in [#7153](https://github.com/danny-avila/Chat/pull/7153)
|
||||
- 🔄 refactor: Artifact Visibility Management by **@danny-avila** in [#7181](https://github.com/danny-avila/Chat/pull/7181)
|
||||
- 📦 chore: Bump Package Security by **@danny-avila** in [#7183](https://github.com/danny-avila/Chat/pull/7183)
|
||||
- 🌿 refactor: Unmount Fork Popover on Hide for Better Performance by **@danny-avila** in [#7189](https://github.com/danny-avila/Chat/pull/7189)
|
||||
- 🧰 chore: ESLint configuration to enforce Prettier formatting rules by **@mawburn** in [#7186](https://github.com/danny-avila/Chat/pull/7186)
|
||||
- 🎨 style: Improve KaTeX Rendering for LaTeX Equations by **@andresgit** in [#7223](https://github.com/danny-avila/Chat/pull/7223)
|
||||
- 📝 docs: Update `.env.example` Google models by **@marlonka** in [#7254](https://github.com/danny-avila/Chat/pull/7254)
|
||||
- 💬 refactor: MCP Chat Visibility Option, Google Rates, Remove OpenAPI Plugins by **@danny-avila** in [#7286](https://github.com/danny-avila/Chat/pull/7286)
|
||||
- 📜 docs: Unreleased Changelog by **@github-actions[bot]** in [#7214](https://github.com/danny-avila/Chat/pull/7214)
|
||||
- 📜 docs: CHANGELOG for release v0.7.8-rc1 by **@github-actions[bot]** in [#7153](https://github.com/danny-avila/LibreChat/pull/7153)
|
||||
- 🔄 refactor: Artifact Visibility Management by **@danny-avila** in [#7181](https://github.com/danny-avila/LibreChat/pull/7181)
|
||||
- 📦 chore: Bump Package Security by **@danny-avila** in [#7183](https://github.com/danny-avila/LibreChat/pull/7183)
|
||||
- 🌿 refactor: Unmount Fork Popover on Hide for Better Performance by **@danny-avila** in [#7189](https://github.com/danny-avila/LibreChat/pull/7189)
|
||||
- 🧰 chore: ESLint configuration to enforce Prettier formatting rules by **@mawburn** in [#7186](https://github.com/danny-avila/LibreChat/pull/7186)
|
||||
- 🎨 style: Improve KaTeX Rendering for LaTeX Equations by **@andresgit** in [#7223](https://github.com/danny-avila/LibreChat/pull/7223)
|
||||
- 📝 docs: Update `.env.example` Google models by **@marlonka** in [#7254](https://github.com/danny-avila/LibreChat/pull/7254)
|
||||
- 💬 refactor: MCP Chat Visibility Option, Google Rates, Remove OpenAPI Plugins by **@danny-avila** in [#7286](https://github.com/danny-avila/LibreChat/pull/7286)
|
||||
- 📜 docs: Unreleased Changelog by **@github-actions[bot]** in [#7214](https://github.com/danny-avila/LibreChat/pull/7214)
|
||||
|
||||
|
||||
|
||||
[See full release details][release-v0.7.8]
|
||||
|
||||
[release-v0.7.8]: https://github.com/danny-avila/Chat/releases/tag/v0.7.8
|
||||
[release-v0.7.8]: https://github.com/danny-avila/LibreChat/releases/tag/v0.7.8
|
||||
|
||||
---
|
||||
## [v0.7.8-rc1] -
|
||||
@@ -96,141 +96,141 @@ Changes from v0.7.7 to v0.7.8-rc1.
|
||||
|
||||
### ✨ New Features
|
||||
|
||||
- 🔍 feat: Mistral OCR API / Upload Files as Text by **@danny-avila** in [#6274](https://github.com/danny-avila/Chat/pull/6274)
|
||||
- 🤖 feat: Support OpenAI Web Search models by **@danny-avila** in [#6313](https://github.com/danny-avila/Chat/pull/6313)
|
||||
- 🔗 feat: Agent Chain (Mixture-of-Agents) by **@danny-avila** in [#6374](https://github.com/danny-avila/Chat/pull/6374)
|
||||
- ⌛ feat: `initTimeout` for Slow Starting MCP Servers by **@perweij** in [#6383](https://github.com/danny-avila/Chat/pull/6383)
|
||||
- 🚀 feat: `S3` Integration for File handling and Image uploads by **@rubentalstra** in [#6142](https://github.com/danny-avila/Chat/pull/6142)
|
||||
- 🔒feat: Enable OpenID Auto-Redirect by **@leondape** in [#6066](https://github.com/danny-avila/Chat/pull/6066)
|
||||
- 🚀 feat: Integrate `Azure Blob Storage` for file handling and image uploads by **@rubentalstra** in [#6153](https://github.com/danny-avila/Chat/pull/6153)
|
||||
- 🚀 feat: Add support for custom `AWS` endpoint in `S3` by **@rubentalstra** in [#6431](https://github.com/danny-avila/Chat/pull/6431)
|
||||
- 🚀 feat: Add support for LDAP STARTTLS in LDAP authentication by **@rubentalstra** in [#6438](https://github.com/danny-avila/Chat/pull/6438)
|
||||
- 🚀 feat: Refactor schema exports and update package version to 0.0.4 by **@rubentalstra** in [#6455](https://github.com/danny-avila/Chat/pull/6455)
|
||||
- 🔼 feat: Add Auto Submit For URL Query Params by **@mjaverto** in [#6440](https://github.com/danny-avila/Chat/pull/6440)
|
||||
- 🛠 feat: Enhance Redis Integration, Rate Limiters & Log Headers by **@danny-avila** in [#6462](https://github.com/danny-avila/Chat/pull/6462)
|
||||
- 💵 feat: Add Automatic Balance Refill by **@rubentalstra** in [#6452](https://github.com/danny-avila/Chat/pull/6452)
|
||||
- 🗣️ feat: add support for gpt-4o-transcribe models by **@berry-13** in [#6483](https://github.com/danny-avila/Chat/pull/6483)
|
||||
- 🎨 feat: UI Refresh for Enhanced UX by **@berry-13** in [#6346](https://github.com/danny-avila/Chat/pull/6346)
|
||||
- 🌍 feat: Add support for Hungarian language localization by **@rubentalstra** in [#6508](https://github.com/danny-avila/Chat/pull/6508)
|
||||
- 🚀 feat: Add Gemini 2.5 Token/Context Values, Increase Max Possible Output to 64k by **@danny-avila** in [#6563](https://github.com/danny-avila/Chat/pull/6563)
|
||||
- 🚀 feat: Enhance MCP Connections For Multi-User Support by **@danny-avila** in [#6610](https://github.com/danny-avila/Chat/pull/6610)
|
||||
- 🚀 feat: Enhance S3 URL Expiry with Refresh; fix: S3 File Deletion by **@danny-avila** in [#6647](https://github.com/danny-avila/Chat/pull/6647)
|
||||
- 🚀 feat: enhance UI components and refactor settings by **@berry-13** in [#6625](https://github.com/danny-avila/Chat/pull/6625)
|
||||
- 💬 feat: move TemporaryChat to the Header by **@berry-13** in [#6646](https://github.com/danny-avila/Chat/pull/6646)
|
||||
- 🚀 feat: Use Model Specs + Specific Endpoints, Limit Providers for Agents by **@danny-avila** in [#6650](https://github.com/danny-avila/Chat/pull/6650)
|
||||
- 🪙 feat: Sync Balance Config on Login by **@danny-avila** in [#6671](https://github.com/danny-avila/Chat/pull/6671)
|
||||
- 🔦 feat: MCP Support for Non-Agent Endpoints by **@danny-avila** in [#6775](https://github.com/danny-avila/Chat/pull/6775)
|
||||
- 🗃️ feat: Code Interpreter File Persistence between Sessions by **@danny-avila** in [#6790](https://github.com/danny-avila/Chat/pull/6790)
|
||||
- 🖥️ feat: Code Interpreter API for Non-Agent Endpoints by **@danny-avila** in [#6803](https://github.com/danny-avila/Chat/pull/6803)
|
||||
- ⚡ feat: Self-hosted Artifacts Static Bundler URL by **@danny-avila** in [#6827](https://github.com/danny-avila/Chat/pull/6827)
|
||||
- 🐳 feat: Add Jemalloc and UV to Docker Builds by **@danny-avila** in [#6836](https://github.com/danny-avila/Chat/pull/6836)
|
||||
- 🤖 feat: GPT-4.1 by **@danny-avila** in [#6880](https://github.com/danny-avila/Chat/pull/6880)
|
||||
- 👋 feat: remove Edge TTS by **@berry-13** in [#6885](https://github.com/danny-avila/Chat/pull/6885)
|
||||
- feat: nav optimization by **@berry-13** in [#5785](https://github.com/danny-avila/Chat/pull/5785)
|
||||
- 🗺️ feat: Add Parameter Location Mapping for OpenAPI actions by **@peeeteeer** in [#6858](https://github.com/danny-avila/Chat/pull/6858)
|
||||
- 🤖 feat: Support `o4-mini` and `o3` Models by **@danny-avila** in [#6928](https://github.com/danny-avila/Chat/pull/6928)
|
||||
- 🎨 feat: OpenAI Image Tools (GPT-Image-1) by **@danny-avila** in [#7079](https://github.com/danny-avila/Chat/pull/7079)
|
||||
- 🗓️ feat: Add Special Variables for Prompts & Agents, Prompt UI Improvements by **@danny-avila** in [#7123](https://github.com/danny-avila/Chat/pull/7123)
|
||||
- 🔍 feat: Mistral OCR API / Upload Files as Text by **@danny-avila** in [#6274](https://github.com/danny-avila/LibreChat/pull/6274)
|
||||
- 🤖 feat: Support OpenAI Web Search models by **@danny-avila** in [#6313](https://github.com/danny-avila/LibreChat/pull/6313)
|
||||
- 🔗 feat: Agent Chain (Mixture-of-Agents) by **@danny-avila** in [#6374](https://github.com/danny-avila/LibreChat/pull/6374)
|
||||
- ⌛ feat: `initTimeout` for Slow Starting MCP Servers by **@perweij** in [#6383](https://github.com/danny-avila/LibreChat/pull/6383)
|
||||
- 🚀 feat: `S3` Integration for File handling and Image uploads by **@rubentalstra** in [#6142](https://github.com/danny-avila/LibreChat/pull/6142)
|
||||
- 🔒feat: Enable OpenID Auto-Redirect by **@leondape** in [#6066](https://github.com/danny-avila/LibreChat/pull/6066)
|
||||
- 🚀 feat: Integrate `Azure Blob Storage` for file handling and image uploads by **@rubentalstra** in [#6153](https://github.com/danny-avila/LibreChat/pull/6153)
|
||||
- 🚀 feat: Add support for custom `AWS` endpoint in `S3` by **@rubentalstra** in [#6431](https://github.com/danny-avila/LibreChat/pull/6431)
|
||||
- 🚀 feat: Add support for LDAP STARTTLS in LDAP authentication by **@rubentalstra** in [#6438](https://github.com/danny-avila/LibreChat/pull/6438)
|
||||
- 🚀 feat: Refactor schema exports and update package version to 0.0.4 by **@rubentalstra** in [#6455](https://github.com/danny-avila/LibreChat/pull/6455)
|
||||
- 🔼 feat: Add Auto Submit For URL Query Params by **@mjaverto** in [#6440](https://github.com/danny-avila/LibreChat/pull/6440)
|
||||
- 🛠 feat: Enhance Redis Integration, Rate Limiters & Log Headers by **@danny-avila** in [#6462](https://github.com/danny-avila/LibreChat/pull/6462)
|
||||
- 💵 feat: Add Automatic Balance Refill by **@rubentalstra** in [#6452](https://github.com/danny-avila/LibreChat/pull/6452)
|
||||
- 🗣️ feat: add support for gpt-4o-transcribe models by **@berry-13** in [#6483](https://github.com/danny-avila/LibreChat/pull/6483)
|
||||
- 🎨 feat: UI Refresh for Enhanced UX by **@berry-13** in [#6346](https://github.com/danny-avila/LibreChat/pull/6346)
|
||||
- 🌍 feat: Add support for Hungarian language localization by **@rubentalstra** in [#6508](https://github.com/danny-avila/LibreChat/pull/6508)
|
||||
- 🚀 feat: Add Gemini 2.5 Token/Context Values, Increase Max Possible Output to 64k by **@danny-avila** in [#6563](https://github.com/danny-avila/LibreChat/pull/6563)
|
||||
- 🚀 feat: Enhance MCP Connections For Multi-User Support by **@danny-avila** in [#6610](https://github.com/danny-avila/LibreChat/pull/6610)
|
||||
- 🚀 feat: Enhance S3 URL Expiry with Refresh; fix: S3 File Deletion by **@danny-avila** in [#6647](https://github.com/danny-avila/LibreChat/pull/6647)
|
||||
- 🚀 feat: enhance UI components and refactor settings by **@berry-13** in [#6625](https://github.com/danny-avila/LibreChat/pull/6625)
|
||||
- 💬 feat: move TemporaryChat to the Header by **@berry-13** in [#6646](https://github.com/danny-avila/LibreChat/pull/6646)
|
||||
- 🚀 feat: Use Model Specs + Specific Endpoints, Limit Providers for Agents by **@danny-avila** in [#6650](https://github.com/danny-avila/LibreChat/pull/6650)
|
||||
- 🪙 feat: Sync Balance Config on Login by **@danny-avila** in [#6671](https://github.com/danny-avila/LibreChat/pull/6671)
|
||||
- 🔦 feat: MCP Support for Non-Agent Endpoints by **@danny-avila** in [#6775](https://github.com/danny-avila/LibreChat/pull/6775)
|
||||
- 🗃️ feat: Code Interpreter File Persistence between Sessions by **@danny-avila** in [#6790](https://github.com/danny-avila/LibreChat/pull/6790)
|
||||
- 🖥️ feat: Code Interpreter API for Non-Agent Endpoints by **@danny-avila** in [#6803](https://github.com/danny-avila/LibreChat/pull/6803)
|
||||
- ⚡ feat: Self-hosted Artifacts Static Bundler URL by **@danny-avila** in [#6827](https://github.com/danny-avila/LibreChat/pull/6827)
|
||||
- 🐳 feat: Add Jemalloc and UV to Docker Builds by **@danny-avila** in [#6836](https://github.com/danny-avila/LibreChat/pull/6836)
|
||||
- 🤖 feat: GPT-4.1 by **@danny-avila** in [#6880](https://github.com/danny-avila/LibreChat/pull/6880)
|
||||
- 👋 feat: remove Edge TTS by **@berry-13** in [#6885](https://github.com/danny-avila/LibreChat/pull/6885)
|
||||
- feat: nav optimization by **@berry-13** in [#5785](https://github.com/danny-avila/LibreChat/pull/5785)
|
||||
- 🗺️ feat: Add Parameter Location Mapping for OpenAPI actions by **@peeeteeer** in [#6858](https://github.com/danny-avila/LibreChat/pull/6858)
|
||||
- 🤖 feat: Support `o4-mini` and `o3` Models by **@danny-avila** in [#6928](https://github.com/danny-avila/LibreChat/pull/6928)
|
||||
- 🎨 feat: OpenAI Image Tools (GPT-Image-1) by **@danny-avila** in [#7079](https://github.com/danny-avila/LibreChat/pull/7079)
|
||||
- 🗓️ feat: Add Special Variables for Prompts & Agents, Prompt UI Improvements by **@danny-avila** in [#7123](https://github.com/danny-avila/LibreChat/pull/7123)
|
||||
|
||||
### 🌍 Internationalization
|
||||
|
||||
- 🌍 i18n: Add Thai Language Support and Update Translations by **@rubentalstra** in [#6219](https://github.com/danny-avila/Chat/pull/6219)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6220](https://github.com/danny-avila/Chat/pull/6220)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6240](https://github.com/danny-avila/Chat/pull/6240)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6241](https://github.com/danny-avila/Chat/pull/6241)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6277](https://github.com/danny-avila/Chat/pull/6277)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6414](https://github.com/danny-avila/Chat/pull/6414)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6505](https://github.com/danny-avila/Chat/pull/6505)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6530](https://github.com/danny-avila/Chat/pull/6530)
|
||||
- 🌍 i18n: Add Persian Localization Support by **@rubentalstra** in [#6669](https://github.com/danny-avila/Chat/pull/6669)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6667](https://github.com/danny-avila/Chat/pull/6667)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#7126](https://github.com/danny-avila/Chat/pull/7126)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#7148](https://github.com/danny-avila/Chat/pull/7148)
|
||||
- 🌍 i18n: Add Thai Language Support and Update Translations by **@rubentalstra** in [#6219](https://github.com/danny-avila/LibreChat/pull/6219)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6220](https://github.com/danny-avila/LibreChat/pull/6220)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6240](https://github.com/danny-avila/LibreChat/pull/6240)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6241](https://github.com/danny-avila/LibreChat/pull/6241)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6277](https://github.com/danny-avila/LibreChat/pull/6277)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6414](https://github.com/danny-avila/LibreChat/pull/6414)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6505](https://github.com/danny-avila/LibreChat/pull/6505)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6530](https://github.com/danny-avila/LibreChat/pull/6530)
|
||||
- 🌍 i18n: Add Persian Localization Support by **@rubentalstra** in [#6669](https://github.com/danny-avila/LibreChat/pull/6669)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#6667](https://github.com/danny-avila/LibreChat/pull/6667)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#7126](https://github.com/danny-avila/LibreChat/pull/7126)
|
||||
- 🌍 i18n: Update translation.json with latest translations by **@github-actions[bot]** in [#7148](https://github.com/danny-avila/LibreChat/pull/7148)
|
||||
|
||||
### 👐 Accessibility
|
||||
|
||||
- 🎨 a11y: Update Model Spec Description Text by **@berry-13** in [#6294](https://github.com/danny-avila/Chat/pull/6294)
|
||||
- 🗑️ a11y: Add Accessible Name to Button for File Attachment Removal by **@kangabell** in [#6709](https://github.com/danny-avila/Chat/pull/6709)
|
||||
- ⌨️ a11y: enhance accessibility & visual consistency by **@berry-13** in [#6866](https://github.com/danny-avila/Chat/pull/6866)
|
||||
- 🙌 a11y: Searchbar/Conversations List Focus by **@danny-avila** in [#7096](https://github.com/danny-avila/Chat/pull/7096)
|
||||
- 👐 a11y: Improve Fork and SplitText Accessibility by **@danny-avila** in [#7147](https://github.com/danny-avila/Chat/pull/7147)
|
||||
- 🎨 a11y: Update Model Spec Description Text by **@berry-13** in [#6294](https://github.com/danny-avila/LibreChat/pull/6294)
|
||||
- 🗑️ a11y: Add Accessible Name to Button for File Attachment Removal by **@kangabell** in [#6709](https://github.com/danny-avila/LibreChat/pull/6709)
|
||||
- ⌨️ a11y: enhance accessibility & visual consistency by **@berry-13** in [#6866](https://github.com/danny-avila/LibreChat/pull/6866)
|
||||
- 🙌 a11y: Searchbar/Conversations List Focus by **@danny-avila** in [#7096](https://github.com/danny-avila/LibreChat/pull/7096)
|
||||
- 👐 a11y: Improve Fork and SplitText Accessibility by **@danny-avila** in [#7147](https://github.com/danny-avila/LibreChat/pull/7147)
|
||||
|
||||
### 🔧 Fixes
|
||||
|
||||
- 🐛 fix: Avatar Type Definitions in Agent/Assistant Schemas by **@danny-avila** in [#6235](https://github.com/danny-avila/Chat/pull/6235)
|
||||
- 🔧 fix: MeiliSearch Field Error and Patch Incorrect Import by #6210 by **@rubentalstra** in [#6245](https://github.com/danny-avila/Chat/pull/6245)
|
||||
- 🔏 fix: Enhance Two-Factor Authentication by **@rubentalstra** in [#6247](https://github.com/danny-avila/Chat/pull/6247)
|
||||
- 🐛 fix: Await saveMessage in abortMiddleware to ensure proper execution by **@sh4shii** in [#6248](https://github.com/danny-avila/Chat/pull/6248)
|
||||
- 🔧 fix: Axios Proxy Usage And Bump `mongoose` by **@danny-avila** in [#6298](https://github.com/danny-avila/Chat/pull/6298)
|
||||
- 🔧 fix: comment out MCP servers to resolve service run issues by **@KunalScriptz** in [#6316](https://github.com/danny-avila/Chat/pull/6316)
|
||||
- 🔧 fix: Update Token Calculations and Mapping, MCP `env` Initialization by **@danny-avila** in [#6406](https://github.com/danny-avila/Chat/pull/6406)
|
||||
- 🐞 fix: Agent "Resend" Message Attachments + Source Icon Styling by **@danny-avila** in [#6408](https://github.com/danny-avila/Chat/pull/6408)
|
||||
- 🐛 fix: Prevent Crash on Duplicate Message ID by **@Odrec** in [#6392](https://github.com/danny-avila/Chat/pull/6392)
|
||||
- 🔐 fix: Invalid Key Length in 2FA Encryption by **@rubentalstra** in [#6432](https://github.com/danny-avila/Chat/pull/6432)
|
||||
- 🏗️ fix: Fix Agents Token Spend Race Conditions, Expand Test Coverage by **@danny-avila** in [#6480](https://github.com/danny-avila/Chat/pull/6480)
|
||||
- 🔃 fix: Draft Clearing, Claude Titles, Remove Default Vision Max Tokens by **@danny-avila** in [#6501](https://github.com/danny-avila/Chat/pull/6501)
|
||||
- 🔧 fix: Update username reference to use user.name in greeting display by **@rubentalstra** in [#6534](https://github.com/danny-avila/Chat/pull/6534)
|
||||
- 🔧 fix: S3 Download Stream with Key Extraction and Blob Storage Encoding for Vision by **@danny-avila** in [#6557](https://github.com/danny-avila/Chat/pull/6557)
|
||||
- 🔧 fix: Mistral type strictness for `usage` & update token values/windows by **@danny-avila** in [#6562](https://github.com/danny-avila/Chat/pull/6562)
|
||||
- 🔧 fix: Consolidate Text Parsing and TTS Edge Initialization by **@danny-avila** in [#6582](https://github.com/danny-avila/Chat/pull/6582)
|
||||
- 🔧 fix: Ensure continuation in image processing on base64 encoding from Blob Storage by **@danny-avila** in [#6619](https://github.com/danny-avila/Chat/pull/6619)
|
||||
- ✉️ fix: Fallback For User Name In Email Templates by **@danny-avila** in [#6620](https://github.com/danny-avila/Chat/pull/6620)
|
||||
- 🔧 fix: Azure Blob Integration and File Source References by **@rubentalstra** in [#6575](https://github.com/danny-avila/Chat/pull/6575)
|
||||
- 🐛 fix: Safeguard against undefined addedEndpoints by **@wipash** in [#6654](https://github.com/danny-avila/Chat/pull/6654)
|
||||
- 🤖 fix: Gemini 2.5 Vision Support by **@danny-avila** in [#6663](https://github.com/danny-avila/Chat/pull/6663)
|
||||
- 🔄 fix: Avatar & Error Handling Enhancements by **@danny-avila** in [#6687](https://github.com/danny-avila/Chat/pull/6687)
|
||||
- 🔧 fix: Chat Middleware, Zod Conversion, Auto-Save and S3 URL Refresh by **@danny-avila** in [#6720](https://github.com/danny-avila/Chat/pull/6720)
|
||||
- 🔧 fix: Agent Capability Checks & DocumentDB Compatibility for Agent Resource Removal by **@danny-avila** in [#6726](https://github.com/danny-avila/Chat/pull/6726)
|
||||
- 🔄 fix: Improve audio MIME type detection and handling by **@berry-13** in [#6707](https://github.com/danny-avila/Chat/pull/6707)
|
||||
- 🪺 fix: Update Role Handling due to New Schema Shape by **@danny-avila** in [#6774](https://github.com/danny-avila/Chat/pull/6774)
|
||||
- 🗨️ fix: Show ModelSpec Greeting by **@berry-13** in [#6770](https://github.com/danny-avila/Chat/pull/6770)
|
||||
- 🔧 fix: Keyv and Proxy Issues, and More Memory Optimizations by **@danny-avila** in [#6867](https://github.com/danny-avila/Chat/pull/6867)
|
||||
- ✨ fix: Implement dynamic text sizing for greeting and name display by **@berry-13** in [#6833](https://github.com/danny-avila/Chat/pull/6833)
|
||||
- 📝 fix: Mistral OCR Image Support and Azure Agent Titles by **@danny-avila** in [#6901](https://github.com/danny-avila/Chat/pull/6901)
|
||||
- 📢 fix: Invalid `engineTTS` and Conversation State on Navigation by **@berry-13** in [#6904](https://github.com/danny-avila/Chat/pull/6904)
|
||||
- 🛠️ fix: Improve Accessibility and Display of Conversation Menu by **@danny-avila** in [#6913](https://github.com/danny-avila/Chat/pull/6913)
|
||||
- 🔧 fix: Agent Resource Form, Convo Menu Style, Ensure Draft Clears on Submission by **@danny-avila** in [#6925](https://github.com/danny-avila/Chat/pull/6925)
|
||||
- 🔀 fix: MCP Improvements, Auto-Save Drafts, Artifact Markup by **@danny-avila** in [#7040](https://github.com/danny-avila/Chat/pull/7040)
|
||||
- 🐋 fix: Improve Deepseek Compatbility by **@danny-avila** in [#7132](https://github.com/danny-avila/Chat/pull/7132)
|
||||
- 🐙 fix: Add Redis Ping Interval to Prevent Connection Drops by **@peeeteeer** in [#7127](https://github.com/danny-avila/Chat/pull/7127)
|
||||
- 🐛 fix: Avatar Type Definitions in Agent/Assistant Schemas by **@danny-avila** in [#6235](https://github.com/danny-avila/LibreChat/pull/6235)
|
||||
- 🔧 fix: MeiliSearch Field Error and Patch Incorrect Import by #6210 by **@rubentalstra** in [#6245](https://github.com/danny-avila/LibreChat/pull/6245)
|
||||
- 🔏 fix: Enhance Two-Factor Authentication by **@rubentalstra** in [#6247](https://github.com/danny-avila/LibreChat/pull/6247)
|
||||
- 🐛 fix: Await saveMessage in abortMiddleware to ensure proper execution by **@sh4shii** in [#6248](https://github.com/danny-avila/LibreChat/pull/6248)
|
||||
- 🔧 fix: Axios Proxy Usage And Bump `mongoose` by **@danny-avila** in [#6298](https://github.com/danny-avila/LibreChat/pull/6298)
|
||||
- 🔧 fix: comment out MCP servers to resolve service run issues by **@KunalScriptz** in [#6316](https://github.com/danny-avila/LibreChat/pull/6316)
|
||||
- 🔧 fix: Update Token Calculations and Mapping, MCP `env` Initialization by **@danny-avila** in [#6406](https://github.com/danny-avila/LibreChat/pull/6406)
|
||||
- 🐞 fix: Agent "Resend" Message Attachments + Source Icon Styling by **@danny-avila** in [#6408](https://github.com/danny-avila/LibreChat/pull/6408)
|
||||
- 🐛 fix: Prevent Crash on Duplicate Message ID by **@Odrec** in [#6392](https://github.com/danny-avila/LibreChat/pull/6392)
|
||||
- 🔐 fix: Invalid Key Length in 2FA Encryption by **@rubentalstra** in [#6432](https://github.com/danny-avila/LibreChat/pull/6432)
|
||||
- 🏗️ fix: Fix Agents Token Spend Race Conditions, Expand Test Coverage by **@danny-avila** in [#6480](https://github.com/danny-avila/LibreChat/pull/6480)
|
||||
- 🔃 fix: Draft Clearing, Claude Titles, Remove Default Vision Max Tokens by **@danny-avila** in [#6501](https://github.com/danny-avila/LibreChat/pull/6501)
|
||||
- 🔧 fix: Update username reference to use user.name in greeting display by **@rubentalstra** in [#6534](https://github.com/danny-avila/LibreChat/pull/6534)
|
||||
- 🔧 fix: S3 Download Stream with Key Extraction and Blob Storage Encoding for Vision by **@danny-avila** in [#6557](https://github.com/danny-avila/LibreChat/pull/6557)
|
||||
- 🔧 fix: Mistral type strictness for `usage` & update token values/windows by **@danny-avila** in [#6562](https://github.com/danny-avila/LibreChat/pull/6562)
|
||||
- 🔧 fix: Consolidate Text Parsing and TTS Edge Initialization by **@danny-avila** in [#6582](https://github.com/danny-avila/LibreChat/pull/6582)
|
||||
- 🔧 fix: Ensure continuation in image processing on base64 encoding from Blob Storage by **@danny-avila** in [#6619](https://github.com/danny-avila/LibreChat/pull/6619)
|
||||
- ✉️ fix: Fallback For User Name In Email Templates by **@danny-avila** in [#6620](https://github.com/danny-avila/LibreChat/pull/6620)
|
||||
- 🔧 fix: Azure Blob Integration and File Source References by **@rubentalstra** in [#6575](https://github.com/danny-avila/LibreChat/pull/6575)
|
||||
- 🐛 fix: Safeguard against undefined addedEndpoints by **@wipash** in [#6654](https://github.com/danny-avila/LibreChat/pull/6654)
|
||||
- 🤖 fix: Gemini 2.5 Vision Support by **@danny-avila** in [#6663](https://github.com/danny-avila/LibreChat/pull/6663)
|
||||
- 🔄 fix: Avatar & Error Handling Enhancements by **@danny-avila** in [#6687](https://github.com/danny-avila/LibreChat/pull/6687)
|
||||
- 🔧 fix: Chat Middleware, Zod Conversion, Auto-Save and S3 URL Refresh by **@danny-avila** in [#6720](https://github.com/danny-avila/LibreChat/pull/6720)
|
||||
- 🔧 fix: Agent Capability Checks & DocumentDB Compatibility for Agent Resource Removal by **@danny-avila** in [#6726](https://github.com/danny-avila/LibreChat/pull/6726)
|
||||
- 🔄 fix: Improve audio MIME type detection and handling by **@berry-13** in [#6707](https://github.com/danny-avila/LibreChat/pull/6707)
|
||||
- 🪺 fix: Update Role Handling due to New Schema Shape by **@danny-avila** in [#6774](https://github.com/danny-avila/LibreChat/pull/6774)
|
||||
- 🗨️ fix: Show ModelSpec Greeting by **@berry-13** in [#6770](https://github.com/danny-avila/LibreChat/pull/6770)
|
||||
- 🔧 fix: Keyv and Proxy Issues, and More Memory Optimizations by **@danny-avila** in [#6867](https://github.com/danny-avila/LibreChat/pull/6867)
|
||||
- ✨ fix: Implement dynamic text sizing for greeting and name display by **@berry-13** in [#6833](https://github.com/danny-avila/LibreChat/pull/6833)
|
||||
- 📝 fix: Mistral OCR Image Support and Azure Agent Titles by **@danny-avila** in [#6901](https://github.com/danny-avila/LibreChat/pull/6901)
|
||||
- 📢 fix: Invalid `engineTTS` and Conversation State on Navigation by **@berry-13** in [#6904](https://github.com/danny-avila/LibreChat/pull/6904)
|
||||
- 🛠️ fix: Improve Accessibility and Display of Conversation Menu by **@danny-avila** in [#6913](https://github.com/danny-avila/LibreChat/pull/6913)
|
||||
- 🔧 fix: Agent Resource Form, Convo Menu Style, Ensure Draft Clears on Submission by **@danny-avila** in [#6925](https://github.com/danny-avila/LibreChat/pull/6925)
|
||||
- 🔀 fix: MCP Improvements, Auto-Save Drafts, Artifact Markup by **@danny-avila** in [#7040](https://github.com/danny-avila/LibreChat/pull/7040)
|
||||
- 🐋 fix: Improve Deepseek Compatbility by **@danny-avila** in [#7132](https://github.com/danny-avila/LibreChat/pull/7132)
|
||||
- 🐙 fix: Add Redis Ping Interval to Prevent Connection Drops by **@peeeteeer** in [#7127](https://github.com/danny-avila/LibreChat/pull/7127)
|
||||
|
||||
### ⚙️ Other Changes
|
||||
|
||||
- 📦 refactor: Move DB Models to `@hanzochat/data-schemas` by **@rubentalstra** in [#6210](https://github.com/danny-avila/Chat/pull/6210)
|
||||
- 📦 chore: Patch `axios` to address CVE-2025-27152 by **@danny-avila** in [#6222](https://github.com/danny-avila/Chat/pull/6222)
|
||||
- ⚠️ refactor: Use Error Content Part Instead Of Throwing Error for Agents by **@danny-avila** in [#6262](https://github.com/danny-avila/Chat/pull/6262)
|
||||
- 🏃♂️ refactor: Improve Agent Run Context & Misc. Changes by **@danny-avila** in [#6448](https://github.com/danny-avila/Chat/pull/6448)
|
||||
- 📝 docs: chat.example.yaml by **@ineiti** in [#6442](https://github.com/danny-avila/Chat/pull/6442)
|
||||
- 🏃♂️ refactor: More Agent Context Improvements during Run by **@danny-avila** in [#6477](https://github.com/danny-avila/Chat/pull/6477)
|
||||
- 🔃 refactor: Allow streaming for `o1` models by **@danny-avila** in [#6509](https://github.com/danny-avila/Chat/pull/6509)
|
||||
- 🔧 chore: `Vite` Plugin Upgrades & Config Optimizations by **@rubentalstra** in [#6547](https://github.com/danny-avila/Chat/pull/6547)
|
||||
- 🔧 refactor: Consolidate Logging, Model Selection & Actions Optimizations, Minor Fixes by **@danny-avila** in [#6553](https://github.com/danny-avila/Chat/pull/6553)
|
||||
- 🎨 style: Address Minor UI Refresh Issues by **@berry-13** in [#6552](https://github.com/danny-avila/Chat/pull/6552)
|
||||
- 🔧 refactor: Enhance Model & Endpoint Configurations with Global Indicators 🌍 by **@berry-13** in [#6578](https://github.com/danny-avila/Chat/pull/6578)
|
||||
- 💬 style: Chat UI, Greeting, and Message adjustments by **@berry-13** in [#6612](https://github.com/danny-avila/Chat/pull/6612)
|
||||
- ⚡ refactor: DocumentDB Compatibility for Balance Updates by **@danny-avila** in [#6673](https://github.com/danny-avila/Chat/pull/6673)
|
||||
- 🧹 chore: Update ESLint rules for React hooks by **@rubentalstra** in [#6685](https://github.com/danny-avila/Chat/pull/6685)
|
||||
- 🪙 chore: Update Gemini Pricing by **@RedwindA** in [#6731](https://github.com/danny-avila/Chat/pull/6731)
|
||||
- 🪺 refactor: Nest Permission fields for Roles by **@rubentalstra** in [#6487](https://github.com/danny-avila/Chat/pull/6487)
|
||||
- 📦 chore: Update `caniuse-lite` dependency to version 1.0.30001706 by **@rubentalstra** in [#6482](https://github.com/danny-avila/Chat/pull/6482)
|
||||
- ⚙️ refactor: OAuth Flow Signal, Type Safety, Tool Progress & Updated Packages by **@danny-avila** in [#6752](https://github.com/danny-avila/Chat/pull/6752)
|
||||
- 📦 chore: bump vite from 6.2.3 to 6.2.5 by **@dependabot[bot]** in [#6745](https://github.com/danny-avila/Chat/pull/6745)
|
||||
- 💾 chore: Enhance Local Storage Handling and Update MCP SDK by **@danny-avila** in [#6809](https://github.com/danny-avila/Chat/pull/6809)
|
||||
- 🤖 refactor: Improve Agents Memory Usage, Bump Keyv, Grok 3 by **@danny-avila** in [#6850](https://github.com/danny-avila/Chat/pull/6850)
|
||||
- 💾 refactor: Enhance Memory In Image Encodings & Client Disposal by **@danny-avila** in [#6852](https://github.com/danny-avila/Chat/pull/6852)
|
||||
- 🔁 refactor: Token Event Handler and Standardize `maxTokens` Key by **@danny-avila** in [#6886](https://github.com/danny-avila/Chat/pull/6886)
|
||||
- 🔍 refactor: Search & Message Retrieval by **@berry-13** in [#6903](https://github.com/danny-avila/Chat/pull/6903)
|
||||
- 🎨 style: standardize dropdown styling & fix z-Index layering by **@berry-13** in [#6939](https://github.com/danny-avila/Chat/pull/6939)
|
||||
- 📙 docs: CONTRIBUTING.md by **@dblock** in [#6831](https://github.com/danny-avila/Chat/pull/6831)
|
||||
- 🧭 refactor: Modernize Nav/Header by **@danny-avila** in [#7094](https://github.com/danny-avila/Chat/pull/7094)
|
||||
- 🪶 refactor: Chat Input Focus for Conversation Navigations & ChatForm Optimizations by **@danny-avila** in [#7100](https://github.com/danny-avila/Chat/pull/7100)
|
||||
- 🔃 refactor: Streamline Navigation, Message Loading UX by **@danny-avila** in [#7118](https://github.com/danny-avila/Chat/pull/7118)
|
||||
- 📜 docs: Unreleased changelog by **@github-actions[bot]** in [#6265](https://github.com/danny-avila/Chat/pull/6265)
|
||||
- 📦 refactor: Move DB Models to `@librechat/data-schemas` by **@rubentalstra** in [#6210](https://github.com/danny-avila/LibreChat/pull/6210)
|
||||
- 📦 chore: Patch `axios` to address CVE-2025-27152 by **@danny-avila** in [#6222](https://github.com/danny-avila/LibreChat/pull/6222)
|
||||
- ⚠️ refactor: Use Error Content Part Instead Of Throwing Error for Agents by **@danny-avila** in [#6262](https://github.com/danny-avila/LibreChat/pull/6262)
|
||||
- 🏃♂️ refactor: Improve Agent Run Context & Misc. Changes by **@danny-avila** in [#6448](https://github.com/danny-avila/LibreChat/pull/6448)
|
||||
- 📝 docs: librechat.example.yaml by **@ineiti** in [#6442](https://github.com/danny-avila/LibreChat/pull/6442)
|
||||
- 🏃♂️ refactor: More Agent Context Improvements during Run by **@danny-avila** in [#6477](https://github.com/danny-avila/LibreChat/pull/6477)
|
||||
- 🔃 refactor: Allow streaming for `o1` models by **@danny-avila** in [#6509](https://github.com/danny-avila/LibreChat/pull/6509)
|
||||
- 🔧 chore: `Vite` Plugin Upgrades & Config Optimizations by **@rubentalstra** in [#6547](https://github.com/danny-avila/LibreChat/pull/6547)
|
||||
- 🔧 refactor: Consolidate Logging, Model Selection & Actions Optimizations, Minor Fixes by **@danny-avila** in [#6553](https://github.com/danny-avila/LibreChat/pull/6553)
|
||||
- 🎨 style: Address Minor UI Refresh Issues by **@berry-13** in [#6552](https://github.com/danny-avila/LibreChat/pull/6552)
|
||||
- 🔧 refactor: Enhance Model & Endpoint Configurations with Global Indicators 🌍 by **@berry-13** in [#6578](https://github.com/danny-avila/LibreChat/pull/6578)
|
||||
- 💬 style: Chat UI, Greeting, and Message adjustments by **@berry-13** in [#6612](https://github.com/danny-avila/LibreChat/pull/6612)
|
||||
- ⚡ refactor: DocumentDB Compatibility for Balance Updates by **@danny-avila** in [#6673](https://github.com/danny-avila/LibreChat/pull/6673)
|
||||
- 🧹 chore: Update ESLint rules for React hooks by **@rubentalstra** in [#6685](https://github.com/danny-avila/LibreChat/pull/6685)
|
||||
- 🪙 chore: Update Gemini Pricing by **@RedwindA** in [#6731](https://github.com/danny-avila/LibreChat/pull/6731)
|
||||
- 🪺 refactor: Nest Permission fields for Roles by **@rubentalstra** in [#6487](https://github.com/danny-avila/LibreChat/pull/6487)
|
||||
- 📦 chore: Update `caniuse-lite` dependency to version 1.0.30001706 by **@rubentalstra** in [#6482](https://github.com/danny-avila/LibreChat/pull/6482)
|
||||
- ⚙️ refactor: OAuth Flow Signal, Type Safety, Tool Progress & Updated Packages by **@danny-avila** in [#6752](https://github.com/danny-avila/LibreChat/pull/6752)
|
||||
- 📦 chore: bump vite from 6.2.3 to 6.2.5 by **@dependabot[bot]** in [#6745](https://github.com/danny-avila/LibreChat/pull/6745)
|
||||
- 💾 chore: Enhance Local Storage Handling and Update MCP SDK by **@danny-avila** in [#6809](https://github.com/danny-avila/LibreChat/pull/6809)
|
||||
- 🤖 refactor: Improve Agents Memory Usage, Bump Keyv, Grok 3 by **@danny-avila** in [#6850](https://github.com/danny-avila/LibreChat/pull/6850)
|
||||
- 💾 refactor: Enhance Memory In Image Encodings & Client Disposal by **@danny-avila** in [#6852](https://github.com/danny-avila/LibreChat/pull/6852)
|
||||
- 🔁 refactor: Token Event Handler and Standardize `maxTokens` Key by **@danny-avila** in [#6886](https://github.com/danny-avila/LibreChat/pull/6886)
|
||||
- 🔍 refactor: Search & Message Retrieval by **@berry-13** in [#6903](https://github.com/danny-avila/LibreChat/pull/6903)
|
||||
- 🎨 style: standardize dropdown styling & fix z-Index layering by **@berry-13** in [#6939](https://github.com/danny-avila/LibreChat/pull/6939)
|
||||
- 📙 docs: CONTRIBUTING.md by **@dblock** in [#6831](https://github.com/danny-avila/LibreChat/pull/6831)
|
||||
- 🧭 refactor: Modernize Nav/Header by **@danny-avila** in [#7094](https://github.com/danny-avila/LibreChat/pull/7094)
|
||||
- 🪶 refactor: Chat Input Focus for Conversation Navigations & ChatForm Optimizations by **@danny-avila** in [#7100](https://github.com/danny-avila/LibreChat/pull/7100)
|
||||
- 🔃 refactor: Streamline Navigation, Message Loading UX by **@danny-avila** in [#7118](https://github.com/danny-avila/LibreChat/pull/7118)
|
||||
- 📜 docs: Unreleased changelog by **@github-actions[bot]** in [#6265](https://github.com/danny-avila/LibreChat/pull/6265)
|
||||
|
||||
|
||||
|
||||
[See full release details][release-v0.7.8-rc1]
|
||||
|
||||
[release-v0.7.8-rc1]: https://github.com/danny-avila/Chat/releases/tag/v0.7.8-rc1
|
||||
[release-v0.7.8-rc1]: https://github.com/danny-avila/LibreChat/releases/tag/v0.7.8-rc1
|
||||
|
||||
---
|
||||
|
||||
+3
-14
@@ -1,9 +1,7 @@
|
||||
# v0.8.3-rc1
|
||||
|
||||
# Base node image — Hanzo Node 24 (Alpine) base: node:sqlite (DatabaseSync) is
|
||||
# built in and native better-sqlite3 compiles (build-base + python3 + g++ baked
|
||||
# in), so the CHAT_STORE_SQLITE document store runs. Node 20 lacked node:sqlite.
|
||||
FROM ghcr.io/hanzoai/nodejs:v24.18.0 AS node
|
||||
# Base node image
|
||||
FROM node:20-alpine AS node
|
||||
|
||||
# Install jemalloc
|
||||
RUN apk add --no-cache jemalloc
|
||||
@@ -20,7 +18,7 @@ COPY --from=ghcr.io/astral-sh/uv:0.9.5-python3.12-alpine /usr/local/bin/uv /usr/
|
||||
RUN uv --version
|
||||
|
||||
# Set configurable max-old-space-size with default
|
||||
ARG NODE_MAX_OLD_SPACE_SIZE=8192
|
||||
ARG NODE_MAX_OLD_SPACE_SIZE=6144
|
||||
|
||||
RUN mkdir -p /app && chown node:node /app
|
||||
WORKDIR /app
|
||||
@@ -44,15 +42,6 @@ RUN \
|
||||
|
||||
COPY --chown=node:node . .
|
||||
|
||||
# Bake the Umami analytics website id into the Vite build so the index.html
|
||||
# %VITE_ANALYTICS_SITE_ID% placeholder is substituted at build time. Vite's HTML
|
||||
# env replacement (loadEnv, envPrefix includes VITE_) picks this up from process.env.
|
||||
# Without it the tracker POSTs a literal "%VITE_ANALYTICS_SITE_ID%" as the website
|
||||
# id and analytics.hanzo.ai/api/send answers 400. Public site identifier (it appears
|
||||
# in the served HTML), safe to default here; override with --build-arg if needed.
|
||||
ARG VITE_ANALYTICS_SITE_ID=2f72b944-f1f8-4d2d-8f6c-26063bde0d1a
|
||||
ENV VITE_ANALYTICS_SITE_ID=$VITE_ANALYTICS_SITE_ID
|
||||
|
||||
RUN \
|
||||
# React client build with configurable memory
|
||||
NODE_OPTIONS="--max-old-space-size=${NODE_MAX_OLD_SPACE_SIZE}" pnpm run frontend; \
|
||||
|
||||
+2
-2
@@ -2,10 +2,10 @@
|
||||
# v0.8.3-rc1
|
||||
|
||||
# Set configurable max-old-space-size with default
|
||||
ARG NODE_MAX_OLD_SPACE_SIZE=8192
|
||||
ARG NODE_MAX_OLD_SPACE_SIZE=6144
|
||||
|
||||
# Base for all builds
|
||||
FROM ghcr.io/hanzoai/nodejs:v24.18.0 AS base-min
|
||||
FROM node:20-alpine AS base-min
|
||||
# Install jemalloc
|
||||
RUN apk add --no-cache jemalloc
|
||||
# Set environment variable to use jemalloc
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
# Build: docker build -f Dockerfile.static -t ghcr.io/hanzoai/chat:latest .
|
||||
# Run: docker run -p 3080:3080 ghcr.io/hanzoai/chat:latest
|
||||
|
||||
FROM ghcr.io/hanzoai/nodejs:v24.18.0
|
||||
FROM node:22-alpine
|
||||
|
||||
RUN npm install -g serve@14
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ AI chat interface with multi-model support,
|
||||
MCP integration, agents, and RAG. Live at **hanzo.chat**.
|
||||
|
||||
**Repo**: `github.com/hanzoai/chat`
|
||||
**Upstream**: Chat (MIT) — internal package names kept (`@hanzochat/*`)
|
||||
**Upstream**: LibreChat (MIT) — internal package names kept (`@librechat/*`)
|
||||
**Package**: `@hanzochat/chat`
|
||||
**Runtime**: Node.js 20 (Alpine)
|
||||
|
||||
@@ -52,7 +52,7 @@ client/ # React frontend (Vite)
|
||||
src/routes/ # Client-side routing
|
||||
src/store/ # State management
|
||||
packages/
|
||||
data-provider/ # Shared data layer (@hanzochat/data-provider)
|
||||
data-provider/ # Shared data layer (librechat-data-provider)
|
||||
data-schemas/ # Validation schemas
|
||||
api/ # API client package (@hanzochat/api)
|
||||
client/ # Shared client components
|
||||
@@ -62,7 +62,7 @@ packages/
|
||||
|
||||
## Configuration
|
||||
|
||||
- `chat.yaml` (or ConfigMap `chat-config` -> `/app/chat.yaml`)
|
||||
- `librechat.yaml` (or ConfigMap `chat-config` -> `/app/librechat.yaml`)
|
||||
- `hanzo-chat.example.yaml` - Hanzo-specific example config
|
||||
- `.env` for secrets
|
||||
|
||||
@@ -92,233 +92,46 @@ CREDS_KEY= CREDS_IV= # Credential encryption
|
||||
|
||||
## Guest Chat (anonymous preview)
|
||||
|
||||
Off by default (`ALLOW_GUEST_CHAT=false`). When enabled, the landing IS the chat
|
||||
composer (ChatGPT-style): an unauthenticated visitor renders the real chat view —
|
||||
composer, starter cards, model picker — WITHOUT logging in, scoped to the free
|
||||
Zen model (`GUEST_MODEL`, default `zen5-flash`) via the `Hanzo` custom endpoint
|
||||
(`api.hanzo.ai`). Prod uses `GUEST_MESSAGE_MAX=2`. Exhausting the quota returns
|
||||
`402 {type:'GUEST_LIMIT'}` and the client opens the existing OpenID/hanzo.id login.
|
||||
|
||||
Client render path (guest === chat, not a marketing gate):
|
||||
- `AuthContext` auto-acquires a guest token when `startupConfig.allowGuestChat`
|
||||
is true (`silentRefresh` fallback + a dedicated effect closing the config race);
|
||||
sets `isGuest=true`, `isAuthenticated=false`. `useAuthRedirect` keeps guests on
|
||||
the chat surface (only truly anonymous, non-guest, non-guest-enabled users go to
|
||||
`/login`). `Root` shows the chat shell for `isAuthenticated || isGuest`.
|
||||
- `ChatRoute` renders `ChatView` for `canChat = isAuthenticated || isGuest`; the
|
||||
`/v1/chat/models` + `/v1/chat/endpoints` queries run for guests (both routes use
|
||||
`requireGuestOrJwtAuth` and return the guest-scoped single-model config), and the
|
||||
roles gate treats a guest as loaded (guests have no agent access). Files:
|
||||
`client/src/routes/{ChatRoute,useAuthRedirect}.tsx`, `hooks/useGuestAuth.ts`,
|
||||
`hooks/AuthContext.tsx`, `components/Auth/GuestLimitDialog.tsx`.
|
||||
Off by default (`ALLOW_GUEST_CHAT=false`). When enabled, unauthenticated
|
||||
visitors get a per-IP free quota (`GUEST_MESSAGE_MAX`, default 3) on the free
|
||||
Zen model (`GUEST_MODEL`, default `zen3-nano`) via the `Hanzo` custom endpoint
|
||||
(`api.hanzo.ai`). Exhausting the quota returns `402 {type:'GUEST_LIMIT'}` and
|
||||
the client opens the existing OpenID/hanzo.id login.
|
||||
|
||||
Security model (fail-closed, server-enforced):
|
||||
- `POST /v1/chat/auth/guest` issues a short-lived guest JWT (`{guest:true}`,
|
||||
per-token random id) signed with `JWT_SECRET`. Rate-limited per IP
|
||||
(`guestTokenLimiter`, `GUEST_TOKEN_MAX`/`GUEST_TOKEN_WINDOW`) so tokens can't be
|
||||
spam-minted.
|
||||
- `requireGuestOrJwtAuth` (chat-completion + guest-safe bootstrap routes: models,
|
||||
endpoints, user, convos, favorites, agents `/chat/active`) accepts guest tokens;
|
||||
the standard `jwt` strategy rejects them everywhere else (no DB user), so every
|
||||
other route stays closed. `enforceGuestScope` pins endpoint+model and strips
|
||||
agents/tools/files/spec/preset. Guests use the shared, capped guest gateway key
|
||||
`GUEST_API_KEY` (the KMS `chat-guest-key`; `HANZO_API_KEY` is the dev fallback),
|
||||
resolved in `packages/api/src/endpoints/custom/initialize.ts` — the guest key's
|
||||
OWN org is metered+capped at the gateway, and per-user `hk-` billing is skipped
|
||||
for `guest` principals (they carry no forwardable bearer and no `X-Org-Id`).
|
||||
- `guestMessageLimiter` enforces the quota against the REAL client IP
|
||||
(`utils/guestClientIp` → Cloudflare `CF-Connecting-IP`, falls back to `req.ip`),
|
||||
NOT the token — clearing cookies / incognito / minting a fresh token does NOT
|
||||
reset it. The store is `limiterCache`, which returns `undefined` when `USE_REDIS`
|
||||
is off → `express-rate-limit` uses its in-process MemoryStore. That store is
|
||||
authoritative at the live deploy's `replicas: 1` + `Recreate` (never two live
|
||||
pods to round-robin); Redis is NOT required (it was killed platform-wide). The
|
||||
only reset is a pod restart — operational, not attacker-triggerable. If guest
|
||||
chat ever scales past one replica, set `USE_REDIS=true` so the count holds
|
||||
across pods.
|
||||
- `POST /api/auth/guest` issues a short-lived guest JWT (`{guest:true}`,
|
||||
per-token random id) signed with `JWT_SECRET`. Rate-limited per IP.
|
||||
- `requireGuestOrJwtAuth` (chat-completion route ONLY) accepts guest tokens;
|
||||
the standard `jwt` strategy rejects them everywhere else (no DB user), so
|
||||
every other route stays closed. `enforceGuestScope` pins endpoint+model and
|
||||
strips agents/tools/files/spec/preset. `guestMessageLimiter` (reuses the
|
||||
Redis `limiterCache`) enforces the per-IP quota.
|
||||
- Key files: `api/server/services/guestConfig.js`,
|
||||
`api/server/controllers/auth/GuestController.js`,
|
||||
`api/server/middleware/{requireGuestOrJwtAuth,enforceGuestScope}.js`,
|
||||
`api/server/middleware/limiters/{guestLimiters,guestMessageLimiter}.js`,
|
||||
`api/server/utils/guestClientIp.js`,
|
||||
router wiring in `api/server/routes/agents/index.js`.
|
||||
- Env: `ALLOW_GUEST_CHAT`, `GUEST_MODEL` (prod `zen5-flash`), `GUEST_ENDPOINT`
|
||||
(`Hanzo`), `GUEST_MESSAGE_MAX` (prod `2`), `GUEST_TOKEN_EXPIRY`, `GUEST_TOKEN_MAX`,
|
||||
`GUEST_TOKEN_WINDOW`. Requires the shared, capped guest key `GUEST_API_KEY`
|
||||
(KMS `chat-guest-key`; falls back to `HANZO_API_KEY`). No Redis dependency at
|
||||
`replicas: 1` — the in-process MemoryStore is the quota's single source of truth.
|
||||
|
||||
## Cloud Agents (canonical /v1/agents)
|
||||
|
||||
Chat can RUN a user's canonical Hanzo Cloud agents (cloud `/v1/agents`, the ONE
|
||||
production agent registry) from the thread — alongside the Chat-legacy local
|
||||
agent builder, which is untouched.
|
||||
|
||||
- Two surfaces, ONE run path: the `/agent <name> [prompt]` slash command and the
|
||||
@mention picker (cloud agents appear as a `cloudAgent` type). Both funnel
|
||||
through `useRunCloudAgent` → `POST /v1/chat/agents/cloud/:name/run`. The @mention /
|
||||
`/agent` picker arms `/agent <name> ` in the composer; submit is intercepted in
|
||||
`ChatForm` (`parseAgentCommand`) and dispatched to the run path.
|
||||
- Server proxy + auth (token never reaches the browser): the chat backend reads
|
||||
the user's hanzo.id token from the server-side session
|
||||
(`req.session.openidTokens.idToken`, then `accessToken`, then the httpOnly
|
||||
cookies) and forwards it as `Authorization: Bearer` to cloud. Cloud's
|
||||
`SanitizeIdentity` (HIP-0026) validates it and pins `X-Org-Id` from the `owner`
|
||||
claim, so a user only ever reaches their OWN org's agents — chat never asserts
|
||||
an org. `requireJwtAuth` gates the proxy (guests rejected); missing token →
|
||||
honest 401, never a service-token fallback (fail-secure). Agent name is
|
||||
validated against cloud's handle grammar (traversal/SSRF guard); it is NOT an
|
||||
open proxy (three fixed endpoints). Principal guard: the on-behalf-of decision
|
||||
keys off the VALIDATED principal (`req.user.provider==='openid'`), not the
|
||||
mutable `token_provider` refresh-strategy cookie, so a local user (who never
|
||||
carries a hanzo.id token) can't run under a stale OpenID session. EVERY
|
||||
forwarded token — id_token preferred, access_token fallback, from session or
|
||||
the httpOnly cookie — must pass `isForwardableToken`: a decodable JWT whose
|
||||
`sub` EQUALS `req.user.openidId` (binding MANDATORY — absent `openidId`/`sub`
|
||||
or a mismatch ⇒ no forward, no fail-open) and is unexpired. Decode-only is
|
||||
sound because cloud does the authoritative JWKS validation over the SAME claims,
|
||||
so it runs as exactly that `sub`; the gate only ever removes a token. An
|
||||
unbindable/expired/foreign token yields an honest 401, never a fabricated or
|
||||
wrong-principal run.
|
||||
- id_token persistence is DECOUPLED from the refresh strategy: OIDC login ALWAYS
|
||||
persists the on-behalf-of BEARER (id_token + access_token) to
|
||||
`req.session.openidTokens` (server-side only), regardless of
|
||||
`OPENID_REUSE_TOKENS`. It does NOT persist the OIDC refresh credential in the
|
||||
decoupled default — the session refreshes via the local JWT cookie, so
|
||||
`session.openidTokens.refreshToken` is written ONLY in REUSE mode (where
|
||||
`refreshController`/`logoutController` read it). That keeps login, refresh AND
|
||||
logout on the local-JWT path byte-identical to a non-OpenID login; that flag
|
||||
SOLELY gates whether `/v1/chat/auth/refresh` performs the OIDC refresh-grant.
|
||||
The ~1h id_token is used while valid; durable refresh (hanzo.id/Casdoor OIDC
|
||||
refresh or an RFC-8693 token-exchange from the chat session) is a tracked
|
||||
FOLLOW-UP — the login-breaking refresh-grant is NOT enabled here.
|
||||
- Abuse limits (a run is a real billable completion): a per-user rate limiter
|
||||
(`cloudAgentLimiter`, `CLOUD_AGENT_USER_MAX`/`CLOUD_AGENT_WINDOW`) guards the
|
||||
whole `/cloud` router; the client caps input by UTF-8 **bytes** (128 KiB), caps
|
||||
the buffered response (4 MiB → 502), and sheds load past a process-wide in-flight
|
||||
ceiling (`CLOUD_AGENT_MAX_CONCURRENT`, 503).
|
||||
- Key files: backend `api/server/services/CloudAgentsClient.js`,
|
||||
`api/server/routes/agents/cloud.js` (mounted `/cloud` in
|
||||
`api/server/routes/agents/index.js`); data layer
|
||||
`packages/data-provider/src/{types/cloudAgents.ts,api-endpoints.ts,data-service.ts}`;
|
||||
client `client/src/hooks/Agents/useRunCloudAgent.ts`,
|
||||
`client/src/utils/agentCommand.ts`,
|
||||
`client/src/components/Chat/Input/AgentsCommand.tsx`, and the @mention wiring in
|
||||
`client/src/hooks/Input/useMentions.ts` + `Mention.tsx`.
|
||||
- Env: `HANZO_CLOUD_URL` (optional; falls back to the `OPENAI_BASE_URL` host).
|
||||
- Convergence path (later): chat's Chat-legacy `/v1/chat/agents` CRUD should
|
||||
converge onto cloud `/v1/agents`; this step only ADDS cloud-agent RUN.
|
||||
|
||||
## Unified cloud architecture (2026-07) — investigate-before-ripping map
|
||||
|
||||
hanzo.chat is the **chat view** of the Hanzo AI cloud (sibling to hanzo.app =
|
||||
builder, console = admin). This section is the honest map of what is ALREADY
|
||||
unified onto the Go backend (`api.hanzo.ai/v1`) vs the one real seam that is not.
|
||||
Verified by full call-graph + route-table trace; do NOT rip blind.
|
||||
|
||||
### What already routes through the Go backend `api.hanzo.ai/v1` (no shadow LLM)
|
||||
|
||||
- **Chat completions**: client `useSSE` → `POST /v1/chat/agents/chat/Hanzo` (all
|
||||
chat, incl. plain-model, goes through the agents framework) → custom-endpoint
|
||||
resolver (`packages/api/src/endpoints/custom/initialize.ts`) reads
|
||||
`HANZO_API_KEY` + literal `baseURL https://api.hanzo.ai/v1` from the loaded
|
||||
config → LangChain OpenAI client → **`POST https://api.hanzo.ai/v1/chat/completions`**
|
||||
(SSE stream, resumable via `GenerationJobManager`). Per-user `hk-` key +
|
||||
per-org Commerce debit; fail-closed 402. THIS is the one inference path.
|
||||
- **Code interpreter** → `CHAT_CODE_BASEURL` = cloud `/v1/exec`.
|
||||
- **Web search** → `webSearch` block (searxng+firecrawl contracts) = cloud
|
||||
`/v1/websearch`.
|
||||
- **Cloud agents** → `POST /v1/chat/agents/cloud/:name/run` server-proxies to cloud
|
||||
`/v1/agents` with the user's hanzo.id bearer (see "Cloud Agents" section).
|
||||
- **Model list**: curated **zen-only** (`fetch:false`) in the loaded config —
|
||||
NO raw upstream names (brand policy). Authoritative prod list lives in the
|
||||
`chat-config` ConfigMap (`universe infra/k8s/chat/configmap.yaml`); repo
|
||||
`chat.yaml` mirrors it (one way).
|
||||
|
||||
### DEAD residue — do NOT treat as a live backend
|
||||
|
||||
- `config.yaml` (LiteLLM `model_list`/`litellm_params`), `docker/Dockerfile.{simple,dev,custom_ui}`
|
||||
(`CMD litellm`), `deploy/migrations/*` (`LiteLLM_*` Prisma tables),
|
||||
`CONTRIBUTING.md` (upstream LiteLLM's), `scripts/cleanup-{litellm,hanzo-chat}.sh`:
|
||||
all **unreferenced** by any compose/k8s/helm/Dockerfile.multi. Prod runs
|
||||
`node server/index.js` and hits `api.hanzo.ai/v1` directly — NO local litellm
|
||||
sidecar. This is upstream merge residue; safe to delete in a dedicated sweep.
|
||||
|
||||
### The ONE real parallel store (FLAG — needs a Go-backend home)
|
||||
|
||||
Chat's Express backend owns, in **MongoDB** (`HanzoChat` DB), all of:
|
||||
`convos`, `messages`, `presets`, `prompts`/`promptGroups`, `users`, `balances`/
|
||||
`transactions`, `files`, `sessions` (refresh-token hashes), plus agents/assistants/
|
||||
memory/RBAC. Schemas: `packages/data-schemas/src/schema/*`. This is the shadow
|
||||
store that is NOT on the Go backend.
|
||||
|
||||
- The Go backend (`hanzoai/ai`, mounted at bare `/v1/*` in cloud) DOES have a
|
||||
persistence home, but under **casibase names** (`/v1/get-chats`, `/v1/get-chat`,
|
||||
`/v1/add-chat`, `/v1/get-messages`, `/v1/add-message`, `/v1/get-usages`) — a
|
||||
different schema/shape than Chat's Mongo.
|
||||
- The canonical OpenAPI repo has `chat/openapi.yaml` describing the INTENDED
|
||||
Chat-shaped REST surface (`/v1/chat/convos`, `/v1/chat/messages`,
|
||||
`/v1/chat/presets`, `/v1/chat/balance`, `/v1/chat/auth/*`) — but the Go binary
|
||||
**does not implement it yet**, and `ai/openapi.yaml` under-documents the real
|
||||
casibase routes.
|
||||
- To truly kill the parallel store WITHOUT breaking live chat: the Go backend
|
||||
(or Base) must implement `chat/openapi.yaml` (conversations/messages/presets),
|
||||
then repoint chat's data layer at it behind a flag and dual-write during
|
||||
cutover. Until then Mongo stays (ripping it = data loss + dead chat).
|
||||
**Coordinate with the openapi agent** (canonical spec + SDK regen).
|
||||
|
||||
### IAM-native auth (HIP-0111) — federated to hanzo.id, LIVE
|
||||
|
||||
- **Prod (backend-proxied)**: Chat passport `openid-client` strategy,
|
||||
OIDC **discovery** from `${OPENID_ISSUER}` = `https://hanzo.id`
|
||||
(`/.well-known/openid-configuration`; discovery fetched via in-cluster
|
||||
`iam.hanzo.svc` to dodge the CF hairpin), client_id **`hanzo-chat`**, callback
|
||||
`/oauth/openid/callback`. Local email/password is OFF in prod
|
||||
(`ALLOW_EMAIL_LOGIN=false`, `ALLOW_REGISTRATION=false`); social OIDC only.
|
||||
Files: `api/strategies/openidStrategy.js`, `api/server/socialLogins.js`,
|
||||
`api/server/routes/oauth.js`. This IS IAM-native (federated), just not the
|
||||
console `@hanzo/iam-js-sdk` shape.
|
||||
- **Static/IAM SPA mode** (`Dockerfile.static`, not the live prod deploy): browser
|
||||
`@hanzo/iam` `BrowserIamSdk` PKCE straight to hanzo.id
|
||||
(`client/src/utils/iam.ts`, `OAuthCallback.tsx`). ⚠️ INCONSISTENCY: uses
|
||||
client_id **`app-chat`** while prod uses `hanzo-chat` — align to `hanzo-chat`.
|
||||
`@hanzo/iam` is pinned `^0.4.0` (HIP-0111 wants ≥0.11.0); this path is dormant.
|
||||
|
||||
### One brand system, but pick the RIGHT one for a Tailwind app
|
||||
|
||||
`@hanzo/ui` and `@hanzo/gui` are **two different, non-overlapping** design systems:
|
||||
- **`@hanzo/ui`** = shadcn/ui + Tailwind + Radix (multi-framework). chat is
|
||||
Vite + React 18 + Tailwind, so THIS is the correct shared lib. Already used:
|
||||
`client/src/components/Nav/HanzoHeader.tsx` mounts `@hanzo/ui/navigation`
|
||||
`HanzoHeader` for cross-app chrome. Monochrome rebrand already done (grey ramp,
|
||||
H mark, favicon = hanzo.app set).
|
||||
- **`@hanzo/gui`** = a **Tamagui** fork (Next.js 15 / React 19, RN-web) — console's
|
||||
stack. Forcing it into the Vite/React18 Chat client = a ground-up rewrite
|
||||
of a live product; NOT done. Unify by widening `@hanzo/ui` adoption + matching
|
||||
console's monochrome tokens, NOT by swapping component frameworks.
|
||||
|
||||
### Config filename caveat
|
||||
|
||||
`loadCustomConfig.js` defaults to **`chat.yaml`** (`CONFIG_PATH || <root>/chat.yaml`).
|
||||
Prod sets `CONFIG_PATH=/app/chat.yaml` (ConfigMap mount). Repo ships
|
||||
`chat.yaml` (reference); a deploy that doesn't set `CONFIG_PATH` to it (or
|
||||
provide `chat.yaml`) falls back to the built-in `openAI` endpoint. `OPENAI_BASE_URL`
|
||||
in `compose.prod.yml` is inert here (built-in openAI reads `OPENAI_REVERSE_PROXY`).
|
||||
router wiring in `api/server/routes/agents/index.js`. Client:
|
||||
`client/src/hooks/useGuestAuth.ts`, `AuthContext.tsx`,
|
||||
`components/Auth/GuestLimitDialog.tsx`.
|
||||
- Env: `ALLOW_GUEST_CHAT`, `GUEST_MESSAGE_MAX`, `GUEST_ENDPOINT`, `GUEST_MODEL`,
|
||||
`GUEST_TOKEN_EXPIRY`, `GUEST_TOKEN_MAX`, `GUEST_TOKEN_WINDOW`. Requires
|
||||
`HANZO_API_KEY` (the free publishable gateway key) and `USE_REDIS` for the
|
||||
shared per-IP quota across replicas.
|
||||
|
||||
## Internal Package Names
|
||||
|
||||
These are kept as-is from upstream (npm deps, not worth renaming):
|
||||
- `@hanzochat/api`, `@hanzochat/client`, `@hanzochat/data-schemas`, `@hanzochat/data-provider`, `@hanzochat/agents`
|
||||
- Functions: `extractChatParams`, `importChatConvo`
|
||||
- Type names: `ChatKeys`, `ChatParams`
|
||||
- Config filename: `chat.yaml` (upstream convention)
|
||||
- Env var: `CHAT_LOG_DIR`
|
||||
- `@hanzochat/api`, `@librechat/client`, `@librechat/data-schemas`, `librechat-data-provider`, `@librechat/agents`
|
||||
- Functions: `extractLibreChatParams`, `importLibreChatConvo`
|
||||
- Type names: `LibreChatKeys`, `LibreChatParams`
|
||||
- Config filename: `librechat.yaml` (upstream convention)
|
||||
- Env var: `LIBRECHAT_LOG_DIR`
|
||||
|
||||
## Branding Cleanup Log
|
||||
|
||||
All user-visible `Chat` / `chat.ai` references replaced with Hanzo equivalents:
|
||||
- All `chat.ai` URLs -> `hanzo.ai/docs/chat/...`
|
||||
- `code.chat.ai` -> `hanzo.ai/docs/chat/code-interpreter/...`
|
||||
All user-visible `LibreChat` / `librechat.ai` references replaced with Hanzo equivalents:
|
||||
- All `librechat.ai` URLs -> `hanzo.ai/docs/chat/...`
|
||||
- `code.librechat.ai` -> `hanzo.ai/docs/chat/code-interpreter/...`
|
||||
- package.json repo URLs -> `github.com/hanzoai/chat`
|
||||
- package.json homepages -> `hanzo.ai/chat`
|
||||
- package.json descriptions -> "Hanzo Chat"
|
||||
@@ -326,6 +139,6 @@ All user-visible `Chat` / `chat.ai` references replaced with Hanzo equivalents:
|
||||
- Docker Compose MongoDB DB name -> `HanzoChat`
|
||||
- GitHub workflow repo refs -> `hanzoai/chat`
|
||||
- MCP User-Agent -> `HanzoChat-MCP-Client`
|
||||
- JSDoc comments: Chat -> Hanzo Chat
|
||||
- Log messages: Chat -> Hanzo Chat
|
||||
- JSDoc comments: LibreChat -> Hanzo Chat
|
||||
- Log messages: LibreChat -> Hanzo Chat
|
||||
- Helm chart URLs -> hanzo.ai/docs/chat/...
|
||||
|
||||
@@ -134,7 +134,7 @@ build-static-local:
|
||||
@echo "$(GREEN)Building static SPA locally...$(NC)"
|
||||
@cp .env.static .env
|
||||
@pnpm run build:data-provider
|
||||
@pnpm run --filter @hanzochat/client build
|
||||
@pnpm run --filter @librechat/client build
|
||||
@cd client && pnpm run build
|
||||
@cp .env.backup .env 2>/dev/null || true
|
||||
@echo "$(GREEN)Local build complete: client/dist/$(NC)"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
chat
|
||||
Copyright (c) 2023 Hanzo AI Inc.
|
||||
|
||||
This product includes software from Chat (https://github.com/danny-avila/Chat), licensed under MIT:
|
||||
This product includes software from LibreChat (https://github.com/danny-avila/LibreChat), licensed under MIT:
|
||||
|
||||
Copyright (c) 2023 Chat (Danny Avila)
|
||||
Copyright (c) 2023 LibreChat (Danny Avila)
|
||||
|
||||
@@ -1,85 +1,168 @@
|
||||
<p align="center"><img src=".github/hero.svg" alt="Hanzo Chat" width="880"></p>
|
||||
<p align="center"><img src=".github/hero.svg" alt="chat" width="880"></p>
|
||||
|
||||
# Hanzo Chat
|
||||
# Hanzo AI Chat
|
||||
|
||||
The chat surface of the Hanzo AI cloud: multi-model chat with agents, tools, and retrieval, running on Hanzo's backend. Live at [hanzo.chat](https://hanzo.chat).
|
||||
AI-powered chat platform with enterprise features, using Hanzo's cloud API or local deployment.
|
||||
|
||||
Hanzo Chat is a sibling to [hanzo.app](https://hanzo.app) (the app builder) and the Hanzo console (admin). All inference, code execution, and web search route through the unified Hanzo API at `api.hanzo.ai/v1`, and sign-in is federated to Hanzo IAM ([hanzo.id](https://hanzo.id)).
|
||||
|
||||
## Features
|
||||
|
||||
- **Multi-model chat** — the Zen model family and other frontier models, served through `api.hanzo.ai`.
|
||||
- **Agents** — build agents in the thread, or run your Hanzo Cloud agents (`/v1/agents`) with an `/agent` command or `@mention`.
|
||||
- **MCP tools** — connect Model Context Protocol servers for tool use.
|
||||
- **RAG** — chat over your own files and documents.
|
||||
- **Web search** — grounded answers via Hanzo web search.
|
||||
- **Code interpreter** — run code in a sandboxed runtime.
|
||||
- **Image generation** — generate images inline.
|
||||
- **Guest chat** — try a free Zen model with no account (optional, off by default).
|
||||
|
||||
## Requirements
|
||||
|
||||
- Node.js 24 (see `.nvmrc`)
|
||||
- pnpm 10
|
||||
- A Hanzo API key — get one at [hanzo.ai/dashboard](https://hanzo.ai/dashboard)
|
||||
|
||||
## Quick start (Docker)
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Clone and setup
|
||||
git clone https://github.com/hanzoai/chat.git
|
||||
cd chat
|
||||
cp .env.example .env # set HANZO_API_KEY
|
||||
|
||||
# Copy environment template
|
||||
cp .env.example .env
|
||||
|
||||
# Edit .env and add your Hanzo API key
|
||||
# Get your key at: https://hanzo.ai/dashboard
|
||||
nano .env
|
||||
|
||||
# Start the platform
|
||||
make up
|
||||
```
|
||||
|
||||
Open http://localhost:3080. `make up` starts the full stack (app, MongoDB, Meilisearch) from `compose.yml`; `make down` stops it.
|
||||
Access the chat at http://localhost:3081
|
||||
|
||||
## Development
|
||||
|
||||
### Basic Development (with hot reload)
|
||||
```bash
|
||||
pnpm install # install workspace dependencies
|
||||
pnpm build:packages # build the shared workspace packages
|
||||
pnpm backend:dev # API server on :3080 (nodemon)
|
||||
pnpm frontend:dev # Vite client dev server (second terminal)
|
||||
make dev
|
||||
```
|
||||
|
||||
Tests and checks:
|
||||
|
||||
### Full Development (with local router)
|
||||
```bash
|
||||
pnpm test:all # all workspace tests
|
||||
pnpm e2e # Playwright end-to-end tests
|
||||
pnpm lint # ESLint
|
||||
pnpm format # Prettier
|
||||
# Set your LLM API keys
|
||||
export ANTHROPIC_API_KEY=your-key
|
||||
export OPENAI_API_KEY=your-key
|
||||
|
||||
# Start full dev stack
|
||||
make dev-full
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────┐ ┌─────────────────────────┐
|
||||
│ Hanzo Chat UI │────▶│ api.hanzo.ai │
|
||||
│ (Hanzo Chat) │ │ (or local router) │
|
||||
│ localhost:3081 │ │ │
|
||||
└─────────────────────────┘ │ • 100+ AI Models │
|
||||
│ │ • MCP Tools │
|
||||
│ │ • Code Execution │
|
||||
▼ └─────────────────────────┘
|
||||
┌─────────────────────────┐
|
||||
│ Local Data Storage │
|
||||
│ • MongoDB (chat history)│
|
||||
│ • Meilisearch (search) │
|
||||
└─────────────────────────┘
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Secrets live in `.env`; the model catalog and endpoints live in `chat.yaml` (copy `chat.example.yaml`). Key variables:
|
||||
### Required Environment Variables
|
||||
|
||||
```env
|
||||
HANZO_API_KEY= # Hanzo API key — inference, tools, search
|
||||
MONGO_URI= # MongoDB connection — chat history, users
|
||||
JWT_SECRET= # session token signing
|
||||
CREDS_KEY= # credential encryption
|
||||
CREDS_IV=
|
||||
# Your Hanzo API key (required)
|
||||
OPENAI_API_KEY=sk-hanzo-your-key-here
|
||||
|
||||
# API endpoint (default: Hanzo cloud)
|
||||
OPENAI_BASE_URL=https://api.hanzo.ai/v1
|
||||
|
||||
# Features
|
||||
MCP_ENABLED=true
|
||||
ALLOW_REGISTRATION=true
|
||||
```
|
||||
|
||||
Sign-in is federated to Hanzo IAM over OpenID Connect (`OPENID_ISSUER=https://hanzo.id`, client `hanzo-chat`).
|
||||
### Optional Customization
|
||||
|
||||
## Workspace
|
||||
```env
|
||||
# Branding
|
||||
APP_TITLE=My AI Assistant
|
||||
CUSTOM_FOOTER=Powered by Hanzo AI
|
||||
|
||||
```
|
||||
api/ Express backend (:3080) — routes, controllers, Mongoose models
|
||||
client/ React frontend (Vite)
|
||||
packages/ data-provider · data-schemas · api · client · agents · mcp
|
||||
# Security
|
||||
JWT_SECRET=your-secret-key
|
||||
```
|
||||
|
||||
## Documentation
|
||||
## Commands
|
||||
|
||||
- Docs: https://hanzo.ai/docs/chat
|
||||
- Deployment, IAM, and platform notes: [`docs/`](./docs)
|
||||
### Basic Usage
|
||||
```bash
|
||||
make up # Start services
|
||||
make down # Stop services
|
||||
make logs # View logs
|
||||
make status # Check health
|
||||
make clean # Remove all data
|
||||
```
|
||||
|
||||
### Development
|
||||
```bash
|
||||
make dev # Dev mode with hot reload
|
||||
make build # Build containers
|
||||
make test # Run tests
|
||||
make lint # Check code quality
|
||||
make format # Format code
|
||||
```
|
||||
|
||||
### Production
|
||||
```bash
|
||||
make prod # Deploy with Traefik
|
||||
make backup # Backup database
|
||||
```
|
||||
|
||||
## Docker Compose Structure
|
||||
|
||||
- `compose.yml` - Base configuration for local development
|
||||
- `compose.dev.yml` - Development overrides (hot reload, local router)
|
||||
- `compose.prod.yml` - Production overrides (Traefik, security)
|
||||
|
||||
## Features
|
||||
|
||||
- 🤖 **100+ AI Models** via Hanzo Router
|
||||
- 💬 **Clean Chat UI** with modern design
|
||||
- 🔍 **Full-Text Search** with Meilisearch
|
||||
- 📝 **Persistent Chat History**
|
||||
- 🛠️ **MCP Tools** for enhanced capabilities
|
||||
- 🚀 **Code Execution** via secure runtime
|
||||
- 🔐 **Enterprise Security** with JWT auth
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Chat not loading
|
||||
```bash
|
||||
# Check service status
|
||||
make status
|
||||
|
||||
# View logs
|
||||
make logs-chat
|
||||
|
||||
# Verify API key
|
||||
echo $OPENAI_API_KEY
|
||||
```
|
||||
|
||||
### Database issues
|
||||
```bash
|
||||
# Reset database
|
||||
make db-reset
|
||||
|
||||
# Export data
|
||||
make db-export
|
||||
|
||||
# Import data
|
||||
make db-import FILE=backup.json
|
||||
```
|
||||
|
||||
## Additional Documentation
|
||||
|
||||
- [Production Deployment](./docs/production-domains.md)
|
||||
- [IAM Integration](./docs/iam-integration.md)
|
||||
- [Platform Overview](./docs/platform-overview.md)
|
||||
- [Demo User Guide](./docs/demo-user.md)
|
||||
|
||||
## Support
|
||||
|
||||
- Documentation: https://docs.hanzo.ai
|
||||
- Issues: https://github.com/hanzoai/chat/issues
|
||||
|
||||
## License
|
||||
|
||||
MIT. MIT licensed. See [LICENSE](./LICENSE) for the full attribution.
|
||||
- Discord: https://discord.gg/hanzoai# CI Test
|
||||
|
||||
+203
-61
@@ -1,85 +1,227 @@
|
||||
<p align="center"><img src=".github/hero.svg" alt="Hanzo Chat" width="880"></p>
|
||||
<!-- Last synced with README.md: 2026-03-28 (cae3888) -->
|
||||
|
||||
# Hanzo Chat
|
||||
<p align="center">
|
||||
<a href="https://librechat.ai">
|
||||
<img src="client/public/assets/logo.svg" height="256">
|
||||
</a>
|
||||
<h1 align="center">
|
||||
<a href="https://librechat.ai">LibreChat</a>
|
||||
</h1>
|
||||
</p>
|
||||
|
||||
Hanzo AI 云的对话入口:多模型对话,内置智能体、工具与检索增强,全部运行在 Hanzo 的后端之上。已上线:[hanzo.chat](https://hanzo.chat)。
|
||||
<p align="center">
|
||||
<a href="README.md">English</a> ·
|
||||
<strong>中文</strong>
|
||||
</p>
|
||||
|
||||
Hanzo Chat 与 [hanzo.app](https://hanzo.app)(应用构建器)和 Hanzo 控制台(管理端)互为姊妹产品。所有推理、代码执行与网页搜索都经由统一的 Hanzo API(`api.hanzo.ai/v1`)完成,登录则联合到 Hanzo IAM([hanzo.id](https://hanzo.id))。
|
||||
<p align="center">
|
||||
<a href="https://discord.librechat.ai">
|
||||
<img
|
||||
src="https://img.shields.io/discord/1086345563026489514?label=&logo=discord&style=for-the-badge&logoWidth=20&logoColor=white&labelColor=000000&color=blueviolet">
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@LibreChat">
|
||||
<img
|
||||
src="https://img.shields.io/badge/YOUTUBE-red.svg?style=for-the-badge&logo=youtube&logoColor=white&labelColor=000000&logoWidth=20">
|
||||
</a>
|
||||
<a href="https://docs.librechat.ai">
|
||||
<img
|
||||
src="https://img.shields.io/badge/DOCS-blue.svg?style=for-the-badge&logo=read-the-docs&logoColor=white&labelColor=000000&logoWidth=20">
|
||||
</a>
|
||||
<a aria-label="Sponsors" href="https://github.com/sponsors/danny-avila">
|
||||
<img
|
||||
src="https://img.shields.io/badge/SPONSORS-brightgreen.svg?style=for-the-badge&logo=github-sponsors&logoColor=white&labelColor=000000&logoWidth=20">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 功能
|
||||
<p align="center">
|
||||
<a href="https://railway.com/deploy/librechat-official?referralCode=HI9hWz&utm_medium=integration&utm_source=readme&utm_campaign=librechat">
|
||||
<img src="https://railway.com/button.svg" alt="Deploy on Railway" height="30">
|
||||
</a>
|
||||
<a href="https://zeabur.com/templates/0X2ZY8">
|
||||
<img src="https://zeabur.com/button.svg" alt="Deploy on Zeabur" height="30"/>
|
||||
</a>
|
||||
<a href="https://template.cloud.sealos.io/deploy?templateName=librechat">
|
||||
<img src="https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg" alt="Deploy on Sealos" height="30">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
- **多模型对话** — Zen 系列模型及其他前沿模型,通过 `api.hanzo.ai` 提供服务。
|
||||
- **智能体** — 在对话中直接构建智能体,或用 `/agent` 命令或 `@提及` 运行你的 Hanzo Cloud 智能体(`/v1/agents`)。
|
||||
- **MCP 工具** — 接入 Model Context Protocol(模型上下文协议)服务器以调用工具。
|
||||
- **检索增强(RAG)** — 基于你自己的文件和文档进行对话。
|
||||
- **网页搜索** — 通过 Hanzo 网页搜索获得有据可循的回答。
|
||||
- **代码解释器** — 在沙箱运行时中执行代码。
|
||||
- **图像生成** — 在对话中直接生成图像。
|
||||
- **访客对话** — 无需注册即可试用免费的 Zen 模型(可选,默认关闭)。
|
||||
<p align="center">
|
||||
<a href="https://www.librechat.ai/docs/translation">
|
||||
<img
|
||||
src="https://img.shields.io/badge/dynamic/json.svg?style=for-the-badge&color=2096F3&label=locize&query=%24.translatedPercentage&url=https://api.locize.app/badgedata/4cb2598b-ed4d-469c-9b04-2ed531a8cb45&suffix=%+translated"
|
||||
alt="翻译进度">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 环境要求
|
||||
|
||||
- Node.js 24(见 `.nvmrc`)
|
||||
- pnpm 10
|
||||
- Hanzo API 密钥 — 在 [hanzo.ai/dashboard](https://hanzo.ai/dashboard) 获取
|
||||
# ✨ 功能
|
||||
|
||||
## 快速开始(Docker)
|
||||
- 🖥️ **UI 与体验**:受 ChatGPT 启发,并具备更强的设计与功能。
|
||||
|
||||
```bash
|
||||
git clone https://github.com/hanzoai/chat.git
|
||||
cd chat
|
||||
cp .env.example .env # 填入 HANZO_API_KEY
|
||||
make up
|
||||
```
|
||||
- 🤖 **AI 模型选择**:
|
||||
- Anthropic (Claude), AWS Bedrock, OpenAI, Azure OpenAI, Google, Vertex AI, OpenAI Responses API (包含 Azure)
|
||||
- [自定义端点 (Custom Endpoints)](https://www.librechat.ai/docs/quick_start/custom_endpoints):LibreChat 支持任何兼容 OpenAI 规范的 API,无需代理。
|
||||
- 兼容[本地与远程 AI 服务商](https://www.librechat.ai/docs/configuration/librechat_yaml/ai_endpoints):
|
||||
- Ollama, groq, Cohere, Mistral AI, Apple MLX, koboldcpp, together.ai,
|
||||
- OpenRouter, Helicone, Perplexity, ShuttleAI, Deepseek, Qwen 等。
|
||||
|
||||
打开 http://localhost:3080。`make up` 会从 `compose.yml` 启动完整技术栈(应用、MongoDB、Meilisearch);`make down` 停止。
|
||||
- 🔧 **[代码解释器 (Code Interpreter) API](https://www.librechat.ai/docs/features/code_interpreter)**:
|
||||
- 安全的沙箱执行环境,支持 Python, Node.js (JS/TS), Go, C/C++, Java, PHP, Rust 和 Fortran。
|
||||
- 无缝文件处理:直接上传、处理并下载文件。
|
||||
- 隐私无忧:完全隔离且安全的执行环境。
|
||||
|
||||
## 开发
|
||||
- 🔦 **智能体与工具集成**:
|
||||
- **[LibreChat 智能体 (Agents)](https://www.librechat.ai/docs/features/agents)**:
|
||||
- 无代码定制助手:无需编程即可构建专业化的 AI 驱动助手。
|
||||
- 智能体市场:发现并部署社区构建的智能体。
|
||||
- 协作共享:与特定用户和群组共享智能体。
|
||||
- 灵活且可扩展:支持 MCP 服务器、工具、文件搜索、代码执行等。
|
||||
- 兼容自定义端点、OpenAI, Azure, Anthropic, AWS Bedrock, Google, Vertex AI, Responses API 等。
|
||||
- [支持模型上下文协议 (MCP)](https://modelcontextprotocol.io/clients#librechat) 用于工具调用。
|
||||
|
||||
```bash
|
||||
pnpm install # 安装工作区依赖
|
||||
pnpm build:packages # 构建共享的工作区包
|
||||
pnpm backend:dev # API 服务,端口 :3080(nodemon)
|
||||
pnpm frontend:dev # Vite 客户端开发服务器(另开一个终端)
|
||||
```
|
||||
- 🔍 **网页搜索**:
|
||||
- 搜索互联网并检索相关信息以增强 AI 上下文。
|
||||
- 结合搜索提供商、内容爬虫和结果重排序,确保最佳检索效果。
|
||||
- **可定制 Jina 重排序**:配置自定义 Jina API URL 用于重排序服务。
|
||||
- **[了解更多 →](https://www.librechat.ai/docs/features/web_search)**
|
||||
|
||||
测试与检查:
|
||||
- 🪄 **支持代码 Artifacts 的生成式 UI**:
|
||||
- [代码 Artifacts](https://youtu.be/GfTj7O4gmd0?si=WJbdnemZpJzBrJo3) 允许在对话中直接创建 React 组件、HTML 页面和 Mermaid 图表。
|
||||
|
||||
```bash
|
||||
pnpm test:all # 全部工作区测试
|
||||
pnpm e2e # Playwright 端到端测试
|
||||
pnpm lint # ESLint
|
||||
pnpm format # Prettier
|
||||
```
|
||||
- 🎨 **图像生成与编辑**:
|
||||
- 使用 [GPT-Image-1](https://www.librechat.ai/docs/features/image_gen#1--openai-image-tools-recommended) 进行文生图与图生图。
|
||||
- 支持 [DALL-E (3/2)](https://www.librechat.ai/docs/features/image_gen#2--dalle-legacy), [Stable Diffusion](https://www.librechat.ai/docs/features/image_gen#3--stable-diffusion-local), [Flux](https://www.librechat.ai/docs/features/image_gen#4--flux) 或任何 [MCP 服务器](https://www.librechat.ai/docs/features/image_gen#5--model-context-protocol-mcp)。
|
||||
- 根据提示词生成惊艳的视觉效果,或通过指令精修现有图像。
|
||||
|
||||
## 配置
|
||||
- 💾 **预设与上下文管理**:
|
||||
- 创建、保存并分享自定义预设。
|
||||
- 在对话中随时切换 AI 端点和预设。
|
||||
- 编辑、重新提交并通过对话分支继续消息。
|
||||
- 创建并与特定用户和群组共享提示词。
|
||||
- [消息与对话分叉 (Fork)](https://www.librechat.ai/docs/features/fork) 以实现高级上下文控制。
|
||||
|
||||
密钥存放在 `.env` 中;模型目录与端点配置位于 `chat.yaml`(复制 `chat.example.yaml`)。主要变量:
|
||||
- 💬 **多模态与文件交互**:
|
||||
- 使用 Claude 3, GPT-4.5, GPT-4o, o1, Llama-Vision 和 Gemini 上传并分析图像 📸。
|
||||
- 支持通过自定义端点、OpenAI, Azure, Anthropic, AWS Bedrock 和 Google 进行文件对话 🗃️。
|
||||
|
||||
```env
|
||||
HANZO_API_KEY= # Hanzo API 密钥 — 推理、工具、搜索
|
||||
MONGO_URI= # MongoDB 连接 — 对话历史、用户
|
||||
JWT_SECRET= # 会话令牌签名
|
||||
CREDS_KEY= # 凭据加密
|
||||
CREDS_IV=
|
||||
```
|
||||
- 🌎 **多语言 UI**:
|
||||
- English, 中文 (简体), 中文 (繁體), العربية, Deutsch, Español, Français, Italiano
|
||||
- Polski, Português (PT), Português (BR), Русский, 日本語, Svenska, 한국어, Tiếng Việt
|
||||
- Türkçe, Nederlands, עברית, Català, Čeština, Dansk, Eesti, فارسی
|
||||
- Suomi, Magyar, Հայերեն, Bahasa Indonesia, ქართული, Latviešu, ไทย, ئۇيغۇرچە
|
||||
|
||||
登录通过 OpenID Connect 联合到 Hanzo IAM(`OPENID_ISSUER=https://hanzo.id`,客户端 `hanzo-chat`)。
|
||||
- 🧠 **推理 UI**:
|
||||
- 针对 DeepSeek-R1 等思维链/推理 AI 模型的动态推理 UI。
|
||||
|
||||
## 工作区结构
|
||||
- 🎨 **可定制界面**:
|
||||
- 可定制的下拉菜单和界面,同时适配高级用户和初学者。
|
||||
|
||||
```
|
||||
api/ Express 后端(:3080)— 路由、控制器、Mongoose 模型
|
||||
client/ React 前端(Vite)
|
||||
packages/ data-provider · data-schemas · api · client · agents · mcp
|
||||
```
|
||||
- 🌊 **[可恢复流 (Resumable Streams)](https://www.librechat.ai/docs/features/resumable_streams)**:
|
||||
- 永不丢失响应:AI 响应在连接中断后自动重连并继续。
|
||||
- 多标签页与多设备同步:在多个标签页打开同一对话,或在另一设备上继续。
|
||||
- 生产级可靠性:支持从单机部署到基于 Redis 的水平扩展。
|
||||
|
||||
## 文档
|
||||
- 🗣️ **语音与音频**:
|
||||
- 通过语音转文字和文字转语音实现免提对话。
|
||||
- 自动发送并播放音频。
|
||||
- 支持 OpenAI, Azure OpenAI 和 Elevenlabs。
|
||||
|
||||
- 文档:https://hanzo.ai/docs/chat
|
||||
- 部署、IAM 与平台说明:[`docs/`](./docs)
|
||||
- 问题反馈:https://github.com/hanzoai/chat/issues
|
||||
- 📥 **导入与导出对话**:
|
||||
- 从 LibreChat, ChatGPT, Chatbot UI 导入对话。
|
||||
- 将对话导出为截图、Markdown、文本、JSON。
|
||||
|
||||
## 许可证
|
||||
- 🔍 **搜索与发现**:
|
||||
- 搜索所有消息和对话。
|
||||
|
||||
MIT 许可证。MIT 许可证。见 [LICENSE](./LICENSE) 获取完整署名。
|
||||
- 👥 **多用户与安全访问**:
|
||||
- 支持 OAuth2, LDAP 和电子邮件登录的多用户安全认证。
|
||||
- 内置审核系统和 Token 消耗管理工具。
|
||||
|
||||
- ⚙️ **配置与部署**:
|
||||
- 支持代理、反向代理、Docker 及多种部署选项。
|
||||
- 可完全本地运行或部署在云端。
|
||||
|
||||
- 📖 **开源与社区**:
|
||||
- 完全开源且在公众监督下开发。
|
||||
- 社区驱动的开发、支持与反馈。
|
||||
|
||||
[查看我们的文档了解更多功能详情](https://docs.librechat.ai/) 📚
|
||||
|
||||
## 🪶 LibreChat:全方位的 AI 对话平台
|
||||
|
||||
LibreChat 是一个自托管的 AI 对话平台,在一个注重隐私的统一界面中整合了所有主流 AI 服务商。
|
||||
|
||||
除了对话功能外,LibreChat 还提供 AI 智能体、模型上下文协议 (MCP) 支持、Artifacts、代码解释器、自定义操作、对话搜索,以及企业级多用户认证。
|
||||
|
||||
开源、活跃开发中,专为重视 AI 基础设施自主可控的用户而构建。
|
||||
|
||||
---
|
||||
|
||||
## 🌐 资源
|
||||
|
||||
**GitHub 仓库:**
|
||||
- **RAG API:** [github.com/danny-avila/rag_api](https://github.com/danny-avila/rag_api)
|
||||
- **网站:** [github.com/LibreChat-AI/librechat.ai](https://github.com/LibreChat-AI/librechat.ai)
|
||||
|
||||
**其他:**
|
||||
- **官方网站:** [librechat.ai](https://librechat.ai)
|
||||
- **帮助文档:** [librechat.ai/docs](https://librechat.ai/docs)
|
||||
- **博客:** [librechat.ai/blog](https://librechat.ai/blog)
|
||||
|
||||
---
|
||||
|
||||
## 📝 更新日志
|
||||
|
||||
访问发布页面和更新日志以了解最新动态:
|
||||
- [发布页面 (Releases)](https://github.com/danny-avila/LibreChat/releases)
|
||||
- [更新日志 (Changelog)](https://www.librechat.ai/changelog)
|
||||
|
||||
**⚠️ 在更新前请务必查看[更新日志](https://www.librechat.ai/changelog)以了解破坏性更改。**
|
||||
|
||||
---
|
||||
|
||||
## ⭐ Star 历史
|
||||
|
||||
<p align="center">
|
||||
<a href="https://star-history.com/#danny-avila/LibreChat&Date">
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=danny-avila/LibreChat&type=Date&theme=dark" onerror="this.src='https://api.star-history.com/svg?repos=danny-avila/LibreChat&type=Date'" />
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://trendshift.io/repositories/4685" target="_blank" style="padding: 10px;">
|
||||
<img src="https://trendshift.io/api/badge/repositories/4685" alt="danny-avila%2FLibreChat | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/>
|
||||
</a>
|
||||
<a href="https://runacap.com/ross-index/q1-24/" target="_blank" rel="noopener" style="margin-left: 20px;">
|
||||
<img style="width: 260px; height: 56px" src="https://runacap.com/wp-content/uploads/2024/04/ROSS_badge_white_Q1_2024.svg" alt="ROSS Index - 2024年第一季度增长最快的开源初创公司 | Runa Capital" width="260" height="56"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## ✨ 贡献
|
||||
|
||||
欢迎任何形式的贡献、建议、错误报告和修复!
|
||||
|
||||
对于新功能、组件或扩展,请在发送 PR 前开启 issue 进行讨论。
|
||||
|
||||
如果您想帮助我们将 LibreChat 翻译成您的母语,我们非常欢迎!改进翻译不仅能让全球用户更轻松地使用 LibreChat,还能提升整体用户体验。请查看我们的[翻译指南](https://www.librechat.ai/docs/translation)。
|
||||
|
||||
---
|
||||
|
||||
## 💖 感谢所有贡献者
|
||||
|
||||
<a href="https://github.com/danny-avila/LibreChat/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=danny-avila/LibreChat" />
|
||||
</a>
|
||||
|
||||
---
|
||||
|
||||
## 🎉 特别鸣谢
|
||||
|
||||
感谢 [Locize](https://locize.com) 提供的翻译管理工具,支持 LibreChat 的多语言功能。
|
||||
|
||||
<p align="center">
|
||||
<a href="https://locize.com" target="_blank" rel="noopener noreferrer">
|
||||
<img src="https://github.com/user-attachments/assets/d6b70894-6064-475e-bb65-92a9e23e0077" alt="Locize Logo" height="50">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const crypto = require('crypto');
|
||||
const fetch = require('node-fetch');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const {
|
||||
countTokens,
|
||||
getBalanceConfig,
|
||||
@@ -20,7 +20,7 @@ const {
|
||||
isAgentsEndpoint,
|
||||
isEphemeralAgentId,
|
||||
supportsBalanceCheck,
|
||||
} = require('@hanzochat/data-provider');
|
||||
} = require('librechat-data-provider');
|
||||
const {
|
||||
updateMessage,
|
||||
getMessages,
|
||||
@@ -76,7 +76,7 @@ class BaseClient {
|
||||
this.fetchedConvo;
|
||||
/** @type {TMessage[]} */
|
||||
this.currentMessages = [];
|
||||
/** @type {import('@hanzochat/data-provider').VisionModes | undefined} */
|
||||
/** @type {import('librechat-data-provider').VisionModes | undefined} */
|
||||
this.visionMode;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const { z } = require('zod');
|
||||
const axios = require('axios');
|
||||
const { Ollama } = require('ollama');
|
||||
const { sleep } = require('@hanzochat/agents');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { Constants } = require('@hanzochat/data-provider');
|
||||
const { sleep } = require('@librechat/agents');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { Constants } = require('librechat-data-provider');
|
||||
const { resolveHeaders, deriveBaseURL } = require('@hanzochat/api');
|
||||
|
||||
const ollamaPayloadSchema = z.object({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const { Readable } = require('stream');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
|
||||
class TextStream extends Readable {
|
||||
constructor(text, options = {}) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const dedent = require('dedent');
|
||||
const { EModelEndpoint, ArtifactModes } = require('@hanzochat/data-provider');
|
||||
const { EModelEndpoint, ArtifactModes } = require('librechat-data-provider');
|
||||
const { generateShadcnPrompt } = require('~/app/clients/prompts/shadcn-docs/generate');
|
||||
const { components } = require('~/app/clients/prompts/shadcn-docs/components');
|
||||
|
||||
@@ -49,7 +49,7 @@ Artifacts are for substantial, self-contained content that users might modify or
|
||||
4. Add a \`type\` attribute to specify the type of content the artifact represents. Assign one of the following values to the \`type\` attribute:
|
||||
- HTML: "text/html"
|
||||
- The user interface can render single file HTML pages placed within the artifact tags. HTML, JS, and CSS should be in a single file when using the \`text/html\` type.
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/v1/chat/placeholder/400/320" alt="placeholder" />\`
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
|
||||
- The only place external scripts can be imported from is https://cdnjs.cloudflare.com
|
||||
- Mermaid Diagrams: "application/vnd.mermaid"
|
||||
- The user interface will render Mermaid diagrams placed within the artifact tags.
|
||||
@@ -63,7 +63,7 @@ Artifacts are for substantial, self-contained content that users might modify or
|
||||
- The assistant can use prebuilt components from the \`shadcn/ui\` library after it is imported: \`import { Alert, AlertDescription, AlertTitle, AlertDialog, AlertDialogAction } from '/components/ui/alert';\`. If using components from the shadcn/ui library, the assistant mentions this to the user and offers to help them install the components if necessary.
|
||||
- Components MUST be imported from \`/components/ui/name\` and NOT from \`/components/name\` or \`@/components/ui/name\`.
|
||||
- NO OTHER LIBRARIES (e.g. zod, hookform) ARE INSTALLED OR ABLE TO BE IMPORTED.
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/v1/chat/placeholder/400/320" alt="placeholder" />\`
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
|
||||
- If you are unable to follow the above requirements for any reason, don't use artifacts and use regular code blocks instead, which will not attempt to render the component.
|
||||
5. Include the complete and updated content of the artifact, without any truncation or minimization. Don't use "// rest of the code remains the same...".
|
||||
6. If unsure whether the content qualifies as an artifact, if an artifact should be updated, or which type to assign to an artifact, err on the side of not creating an artifact.
|
||||
@@ -162,7 +162,7 @@ Artifacts are for substantial, self-contained content that users might modify or
|
||||
4. Add a \`type\` attribute to specify the type of content the artifact represents. Assign one of the following values to the \`type\` attribute:
|
||||
- HTML: "text/html"
|
||||
- The user interface can render single file HTML pages placed within the artifact tags. HTML, JS, and CSS should be in a single file when using the \`text/html\` type.
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/v1/chat/placeholder/400/320" alt="placeholder" />\`
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
|
||||
- The only place external scripts can be imported from is https://cdnjs.cloudflare.com
|
||||
- SVG: "image/svg+xml"
|
||||
- The user interface will render the Scalable Vector Graphics (SVG) image within the artifact tags.
|
||||
@@ -186,7 +186,7 @@ Artifacts are for substantial, self-contained content that users might modify or
|
||||
- The assistant can use prebuilt components from the \`shadcn/ui\` library after it is imported: \`import { Alert, AlertDescription, AlertTitle, AlertDialog, AlertDialogAction } from '/components/ui/alert';\`. If using components from the shadcn/ui library, the assistant mentions this to the user and offers to help them install the components if necessary.
|
||||
- Components MUST be imported from \`/components/ui/name\` and NOT from \`/components/name\` or \`@/components/ui/name\`.
|
||||
- NO OTHER LIBRARIES (e.g. zod, hookform) ARE INSTALLED OR ABLE TO BE IMPORTED.
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/v1/chat/placeholder/400/320" alt="placeholder" />\`
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
|
||||
- When iterating on code, ensure that the code is complete and functional without any snippets, placeholders, or ellipses.
|
||||
- If you are unable to follow the above requirements for any reason, don't use artifacts and use regular code blocks instead, which will not attempt to render the component.
|
||||
5. Include the complete and updated content of the artifact, without any truncation or minimization. Don't use "// rest of the code remains the same...".
|
||||
@@ -367,7 +367,7 @@ Artifacts are for substantial, self-contained content that users might modify or
|
||||
4. Add a \`type\` attribute to specify the type of content the artifact represents. Assign one of the following values to the \`type\` attribute:
|
||||
- HTML: "text/html"
|
||||
- The user interface can render single file HTML pages placed within the artifact tags. HTML, JS, and CSS should be in a single file when using the \`text/html\` type.
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/v1/chat/placeholder/400/320" alt="placeholder" />\`
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
|
||||
- The only place external scripts can be imported from is https://cdnjs.cloudflare.com
|
||||
- SVG: "image/svg+xml"
|
||||
- The user interface will render the Scalable Vector Graphics (SVG) image within the artifact tags.
|
||||
@@ -391,7 +391,7 @@ Artifacts are for substantial, self-contained content that users might modify or
|
||||
- The assistant can use prebuilt components from the \`shadcn/ui\` library after it is imported: \`import { Alert, AlertDescription, AlertTitle, AlertDialog, AlertDialogAction } from '/components/ui/alert';\`. If using components from the shadcn/ui library, the assistant mentions this to the user and offers to help them install the components if necessary.
|
||||
- Components MUST be imported from \`/components/ui/name\` and NOT from \`/components/name\` or \`@/components/ui/name\`.
|
||||
- NO OTHER LIBRARIES (e.g. zod, hookform) ARE INSTALLED OR ABLE TO BE IMPORTED.
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/v1/chat/placeholder/400/320" alt="placeholder" />\`
|
||||
- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so \`<img src="/api/placeholder/400/320" alt="placeholder" />\`
|
||||
- When iterating on code, ensure that the code is complete and functional without any snippets, placeholders, or ellipses.
|
||||
- If you are unable to follow the above requirements for any reason, don't use artifacts and use regular code blocks instead, which will not attempt to render the component.
|
||||
5. Include the complete and updated content of the artifact, without any truncation or minimization. Don't use "// rest of the code remains the same...".
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const axios = require('axios');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { isEnabled, generateShortLivedToken } = require('@hanzochat/api');
|
||||
|
||||
const footer = `Use the context as your learned knowledge to better answer the user.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const { ToolMessage } = require('@langchain/core/messages');
|
||||
const { ContentTypes } = require('@hanzochat/data-provider');
|
||||
const { ContentTypes } = require('librechat-data-provider');
|
||||
const { HumanMessage, AIMessage, SystemMessage } = require('@langchain/core/messages');
|
||||
const { formatAgentMessages } = require('./formatMessages');
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const { ToolMessage } = require('@langchain/core/messages');
|
||||
const { EModelEndpoint, ContentTypes } = require('@hanzochat/data-provider');
|
||||
const { EModelEndpoint, ContentTypes } = require('librechat-data-provider');
|
||||
const { HumanMessage, AIMessage, SystemMessage } = require('@langchain/core/messages');
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { Constants } = require('@hanzochat/data-provider');
|
||||
const { Constants } = require('librechat-data-provider');
|
||||
const { HumanMessage, AIMessage, SystemMessage } = require('@langchain/core/messages');
|
||||
const { formatMessage, formatLangChainMessages, formatFromLangChain } = require('./formatMessages');
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { Constants } = require('@hanzochat/data-provider');
|
||||
const { Constants } = require('librechat-data-provider');
|
||||
const { initializeFakeClient } = require('./FakeClient');
|
||||
|
||||
jest.mock('~/db/connect');
|
||||
@@ -40,8 +40,8 @@ jest.mock('~/models', () => ({
|
||||
|
||||
const { getConvo, saveConvo } = require('~/models');
|
||||
|
||||
jest.mock('@hanzochat/agents', () => {
|
||||
const actual = jest.requireActual('@hanzochat/agents');
|
||||
jest.mock('@librechat/agents', () => {
|
||||
const actual = jest.requireActual('@librechat/agents');
|
||||
return {
|
||||
...actual,
|
||||
ChatOpenAI: jest.fn().mockImplementation(() => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const { Tool } = require('@langchain/core/tools');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { SearchClient, AzureKeyCredential } = require('@azure/search-documents');
|
||||
|
||||
const azureAISearchJsonSchema = {
|
||||
|
||||
@@ -3,9 +3,9 @@ const OpenAI = require('openai');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const { ProxyAgent, fetch } = require('undici');
|
||||
const { Tool } = require('@langchain/core/tools');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { getImageBasename, extractBaseURL } = require('@hanzochat/api');
|
||||
const { FileContext, ContentTypes } = require('@hanzochat/data-provider');
|
||||
const { FileContext, ContentTypes } = require('librechat-data-provider');
|
||||
|
||||
const dalle3JsonSchema = {
|
||||
type: 'object',
|
||||
@@ -143,26 +143,16 @@ class DALLE3 extends Tool {
|
||||
throw new Error('Missing required field: prompt');
|
||||
}
|
||||
|
||||
// Model is configurable (DALLE3_MODEL) so this tool drives the Hanzo image
|
||||
// family (e.g. zen3-image) through the same OpenAI /images/generations shape.
|
||||
// `quality` and `style` are DALL-E-3-only knobs — send them ONLY for a dall-e
|
||||
// model so a non-DALL-E backend never sees a parameter it may reject.
|
||||
const model = process.env.DALLE3_MODEL || 'dall-e-3';
|
||||
const isDallE = model.startsWith('dall-e');
|
||||
const genParams = {
|
||||
model,
|
||||
size,
|
||||
prompt: this.replaceUnwantedChars(prompt),
|
||||
n: 1,
|
||||
};
|
||||
if (isDallE) {
|
||||
genParams.quality = quality;
|
||||
genParams.style = style;
|
||||
}
|
||||
|
||||
let resp;
|
||||
try {
|
||||
resp = await this.openai.images.generate(genParams);
|
||||
resp = await this.openai.images.generate({
|
||||
model: 'dall-e-3',
|
||||
quality,
|
||||
style,
|
||||
size,
|
||||
prompt: this.replaceUnwantedChars(prompt),
|
||||
n: 1,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('[DALL-E-3] Problem generating the image:', error);
|
||||
return this
|
||||
|
||||
@@ -2,9 +2,9 @@ const axios = require('axios');
|
||||
const fetch = require('node-fetch');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const { Tool } = require('@langchain/core/tools');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent');
|
||||
const { FileContext, ContentTypes } = require('@hanzochat/data-provider');
|
||||
const { FileContext, ContentTypes } = require('librechat-data-provider');
|
||||
|
||||
const fluxApiJsonSchema = {
|
||||
type: 'object',
|
||||
|
||||
@@ -5,13 +5,13 @@ const { v4 } = require('uuid');
|
||||
const { ProxyAgent } = require('undici');
|
||||
const { GoogleGenAI } = require('@google/genai');
|
||||
const { tool } = require('@langchain/core/tools');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const {
|
||||
FileContext,
|
||||
ContentTypes,
|
||||
FileSources,
|
||||
EImageOutputType,
|
||||
} = require('@hanzochat/data-provider');
|
||||
} = require('librechat-data-provider');
|
||||
const {
|
||||
geminiToolkit,
|
||||
loadServiceKey,
|
||||
|
||||
@@ -4,9 +4,9 @@ const OpenAI = require('openai');
|
||||
const FormData = require('form-data');
|
||||
const { ProxyAgent } = require('undici');
|
||||
const { tool } = require('@langchain/core/tools');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { HttpsProxyAgent } = require('https-proxy-agent');
|
||||
const { ContentTypes, EImageOutputType } = require('@hanzochat/data-provider');
|
||||
const { ContentTypes, EImageOutputType } = require('librechat-data-provider');
|
||||
const { logAxiosError, oaiToolkit, extractBaseURL } = require('@hanzochat/api');
|
||||
const { getStrategyFunctions } = require('~/server/services/Files/strategies');
|
||||
const { getFiles } = require('~/models');
|
||||
|
||||
@@ -5,8 +5,8 @@ const axios = require('axios');
|
||||
const sharp = require('sharp');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const { Tool } = require('@langchain/core/tools');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { FileContext, ContentTypes } = require('@hanzochat/data-provider');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { FileContext, ContentTypes } = require('librechat-data-provider');
|
||||
const { getBasePath } = require('@hanzochat/api');
|
||||
const paths = require('~/config/paths');
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const { Tool } = require('@langchain/core/tools');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { getEnvironmentVariable } = require('@langchain/core/utils/env');
|
||||
|
||||
const traversaalSearchJsonSchema = {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-useless-escape */
|
||||
const axios = require('axios');
|
||||
const { Tool } = require('@langchain/core/tools');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
|
||||
const wolframJsonSchema = {
|
||||
type: 'object',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const OpenAI = require('openai');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const DALLE3 = require('../DALLE3');
|
||||
|
||||
jest.mock('openai');
|
||||
jest.mock('@hanzochat/data-schemas', () => {
|
||||
jest.mock('@librechat/data-schemas', () => {
|
||||
return {
|
||||
logger: {
|
||||
info: jest.fn(),
|
||||
|
||||
@@ -12,8 +12,8 @@ const axios = require('axios');
|
||||
const OpenAI = require('openai');
|
||||
const undici = require('undici');
|
||||
const fetch = require('node-fetch');
|
||||
const { ContentTypes } = require('@hanzochat/data-provider');
|
||||
const { ToolMessage } = require('@hanzochat/agents/langchain/messages');
|
||||
const { ContentTypes } = require('librechat-data-provider');
|
||||
const { ToolMessage } = require('@librechat/agents/langchain/messages');
|
||||
const StableDiffusionAPI = require('../StableDiffusion');
|
||||
const FluxAPI = require('../FluxAPI');
|
||||
const DALLE3 = require('../DALLE3');
|
||||
@@ -25,7 +25,7 @@ jest.mock('undici', () => ({
|
||||
ProxyAgent: jest.fn(),
|
||||
fetch: jest.fn(),
|
||||
}));
|
||||
jest.mock('@hanzochat/data-schemas', () => ({
|
||||
jest.mock('@librechat/data-schemas', () => ({
|
||||
logger: { info: jest.fn(), warn: jest.fn(), debug: jest.fn(), error: jest.fn() },
|
||||
}));
|
||||
jest.mock('path', () => ({
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const axios = require('axios');
|
||||
const { tool } = require('@langchain/core/tools');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { generateShortLivedToken } = require('@hanzochat/api');
|
||||
const { Tools, EToolResources } = require('@hanzochat/data-provider');
|
||||
const { Tools, EToolResources } = require('librechat-data-provider');
|
||||
const { filterFilesByAgentAccess } = require('~/server/services/Files/permissions');
|
||||
const { getFiles } = require('~/models');
|
||||
|
||||
@@ -97,7 +97,7 @@ const createFileSearchTool = async ({ userId, files, entity_id, fileCitations =
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@hanzochat/data-provider').TFile} file
|
||||
* @param {import('librechat-data-provider').TFile} file
|
||||
* @returns {{ file_id: string, query: string, k: number, entity_id?: string }}
|
||||
*/
|
||||
const createQueryBody = (file) => {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const {
|
||||
EnvVar,
|
||||
Calculator,
|
||||
createSearchTool,
|
||||
createCodeExecutionTool,
|
||||
} = require('@hanzochat/agents');
|
||||
} = require('@librechat/agents');
|
||||
const {
|
||||
checkAccess,
|
||||
createSafeUser,
|
||||
@@ -12,8 +12,6 @@ const {
|
||||
loadWebSearchAuth,
|
||||
buildImageToolContext,
|
||||
buildWebSearchContext,
|
||||
resolveTenantBearer,
|
||||
OPENID_BEARER_SENTINEL,
|
||||
} = require('@hanzochat/api');
|
||||
const { getMCPServersRegistry } = require('~/config');
|
||||
const {
|
||||
@@ -22,7 +20,7 @@ const {
|
||||
Permissions,
|
||||
EToolResources,
|
||||
PermissionTypes,
|
||||
} = require('@hanzochat/data-provider');
|
||||
} = require('librechat-data-provider');
|
||||
const {
|
||||
availableTools,
|
||||
manifestToolMap,
|
||||
@@ -234,29 +232,7 @@ const loadTools = async ({
|
||||
const requestedTools = {};
|
||||
|
||||
if (functions === true) {
|
||||
// dalle (image generation) drives the Hanzo image family via a PER-USER hk-
|
||||
// key so generation is metered to the signed-in user — mirroring the chat
|
||||
// per-user key path in custom/initialize.ts. A guest keeps the shared env
|
||||
// key; an authenticated user whose key cannot be resolved FAILS CLOSED
|
||||
// (throws) rather than silently billing the shared org. (Custom constructors
|
||||
// take precedence over the generic toolConstructors path in the loop below.)
|
||||
customConstructors.dalle = async () => {
|
||||
const authFields = getAuthFields('dalle');
|
||||
const authValues = await loadAuthValues({ userId: user, authFields });
|
||||
// Canonical Hanzo Cloud billing (mirrors custom/initialize.ts): when the
|
||||
// image endpoint is configured to forward the user's IAM bearer
|
||||
// (DALLE3_API_KEY === the OIDC-token sentinel), resolve the signed-in
|
||||
// user's own IAM token and forward it so cloud meters THEIR org. Fail
|
||||
// closed if there is no forwardable bearer — no shared key to spend.
|
||||
if (authValues.DALLE3_API_KEY === OPENID_BEARER_SENTINEL) {
|
||||
const bearer = resolveTenantBearer(options.req);
|
||||
if (!bearer) {
|
||||
throw new Error('Sign in with Hanzo to generate images — your Hanzo account funds this request.');
|
||||
}
|
||||
authValues.DALLE3_API_KEY = bearer;
|
||||
}
|
||||
return new DALLE3({ ...imageGenOptions, ...authValues, userId: user });
|
||||
};
|
||||
toolConstructors.dalle = DALLE3;
|
||||
}
|
||||
|
||||
/** @type {ImageGenOptions} */
|
||||
|
||||
@@ -30,7 +30,7 @@ jest.mock('~/server/services/Config', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const { Calculator } = require('@hanzochat/agents');
|
||||
const { Calculator } = require('@librechat/agents');
|
||||
|
||||
const { User } = require('~/db/models');
|
||||
const PluginService = require('~/server/services/PluginService');
|
||||
|
||||
Vendored
+2
-2
@@ -1,6 +1,6 @@
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { isEnabled, math } = require('@hanzochat/api');
|
||||
const { ViolationTypes } = require('@hanzochat/data-provider');
|
||||
const { ViolationTypes } = require('librechat-data-provider');
|
||||
const { deleteAllUserSessions } = require('~/models');
|
||||
const { removePorts } = require('~/server/utils');
|
||||
const getLogStores = require('./getLogStores');
|
||||
|
||||
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
||||
const { isEnabled } = require('@hanzochat/api');
|
||||
const { Time, CacheKeys } = require('@hanzochat/data-provider');
|
||||
const { Time, CacheKeys } = require('librechat-data-provider');
|
||||
const getLogStores = require('./getLogStores');
|
||||
|
||||
const { USE_REDIS, LIMIT_CONCURRENT_MESSAGES } = process.env ?? {};
|
||||
|
||||
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
||||
const { Keyv } = require('keyv');
|
||||
const { Time, CacheKeys, ViolationTypes } = require('@hanzochat/data-provider');
|
||||
const { Time, CacheKeys, ViolationTypes } = require('librechat-data-provider');
|
||||
const {
|
||||
logFile,
|
||||
keyvMongo,
|
||||
|
||||
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
||||
const { isEnabled } = require('@hanzochat/api');
|
||||
const { ViolationTypes } = require('@hanzochat/data-provider');
|
||||
const { ViolationTypes } = require('librechat-data-provider');
|
||||
const getLogStores = require('./getLogStores');
|
||||
const banViolation = require('./banViolation');
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ const fs = require('fs');
|
||||
const ORIGINAL_ENV = process.env;
|
||||
|
||||
const mockDataSchemas = () => {
|
||||
jest.doMock('@hanzochat/data-schemas', () => ({
|
||||
jest.doMock('@librechat/data-schemas', () => ({
|
||||
getTenantId: jest.fn(),
|
||||
getUserId: jest.fn(),
|
||||
getRequestId: jest.fn(),
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
const { EventSource } = require('eventsource');
|
||||
const { Time } = require('@hanzochat/data-provider');
|
||||
const { Time } = require('librechat-data-provider');
|
||||
const {
|
||||
MCPManager,
|
||||
FlowStateManager,
|
||||
|
||||
@@ -6,13 +6,13 @@ require('winston-daily-rotate-file');
|
||||
/**
|
||||
* Determine the log directory.
|
||||
* Priority:
|
||||
* 1. CHAT_LOG_DIR environment variable (allows user override)
|
||||
* 1. LIBRECHAT_LOG_DIR environment variable (allows user override)
|
||||
* 2. /app/logs if running in Docker (bind-mounted with correct permissions)
|
||||
* 3. api/logs relative to this file (local development)
|
||||
*/
|
||||
const getLogDir = () => {
|
||||
if (process.env.CHAT_LOG_DIR) {
|
||||
return process.env.CHAT_LOG_DIR;
|
||||
if (process.env.LIBRECHAT_LOG_DIR) {
|
||||
return process.env.LIBRECHAT_LOG_DIR;
|
||||
}
|
||||
|
||||
// Check if running in Docker container (cwd is /app)
|
||||
|
||||
@@ -7,13 +7,13 @@ const { redactFormat, redactMessage, debugTraverse, jsonTruncateFormat } = requi
|
||||
/**
|
||||
* Determine the log directory.
|
||||
* Priority:
|
||||
* 1. CHAT_LOG_DIR environment variable (allows user override)
|
||||
* 1. LIBRECHAT_LOG_DIR environment variable (allows user override)
|
||||
* 2. /app/logs if running in Docker (bind-mounted with correct permissions)
|
||||
* 3. api/logs relative to this file (local development)
|
||||
*/
|
||||
const getLogDir = () => {
|
||||
if (process.env.CHAT_LOG_DIR) {
|
||||
return process.env.CHAT_LOG_DIR;
|
||||
if (process.env.LIBRECHAT_LOG_DIR) {
|
||||
return process.env.LIBRECHAT_LOG_DIR;
|
||||
}
|
||||
|
||||
// Check if running in Docker container (cwd is /app)
|
||||
|
||||
+4
-16
@@ -1,15 +1,13 @@
|
||||
require('dotenv').config();
|
||||
const { isEnabled } = require('@hanzochat/api');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
const MONGO_URI = process.env.MONGO_URI;
|
||||
|
||||
// MONGO_URI is intentionally optional: in SQLite-only mode (every collection
|
||||
// served from CHAT_STORE_SQLITE, chat-docdb deleted) there is no Mongo to
|
||||
// connect to. connectDb() below handles the unset case by skipping the
|
||||
// connection rather than failing boot. When MONGO_URI IS set (default and the
|
||||
// dual-write migration window) the connection is required as before.
|
||||
if (!MONGO_URI) {
|
||||
throw new Error('Please define the MONGO_URI environment variable');
|
||||
}
|
||||
/** The maximum number of connections in the connection pool. */
|
||||
const maxPoolSize = parseInt(process.env.MONGO_MAX_POOL_SIZE) || undefined;
|
||||
/** The minimum number of connections in the connection pool. */
|
||||
@@ -47,16 +45,6 @@ mongoose.connection.on('error', (err) => {
|
||||
});
|
||||
|
||||
async function connectDb() {
|
||||
if (!MONGO_URI) {
|
||||
// SQLite-only mode: skip Mongo entirely. Disable command buffering so any
|
||||
// stray mongoose query (e.g. Meili indexSync, which still references
|
||||
// mongoose.models directly) fails fast and is swallowed by its caller
|
||||
// instead of hanging forever on a pool that will never connect.
|
||||
mongoose.set('bufferCommands', false);
|
||||
logger.info('[connectDb] MONGO_URI unset — SQLite-only mode, skipping MongoDB connection');
|
||||
return null;
|
||||
}
|
||||
|
||||
if (cached.conn && cached.conn?._readyState === 1) {
|
||||
return cached.conn;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
const mongoose = require('mongoose');
|
||||
const { createModels } = require('@hanzochat/data-schemas');
|
||||
const { createModels } = require('@librechat/data-schemas');
|
||||
const { connectDb } = require('./connect');
|
||||
const indexSync = require('./indexSync');
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ describe('api/db/index.js', () => {
|
||||
|
||||
const callOrder = [];
|
||||
|
||||
jest.mock('@hanzochat/data-schemas', () => ({
|
||||
jest.mock('@librechat/data-schemas', () => ({
|
||||
createModels: jest.fn((m) => {
|
||||
callOrder.push('createModels');
|
||||
m.models.Message = { name: 'Message' };
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
const mongoose = require('mongoose');
|
||||
const { MeiliSearch } = require('meilisearch');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { CacheKeys } = require('@hanzochat/data-provider');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { CacheKeys } = require('librechat-data-provider');
|
||||
const { isEnabled, FlowStateManager } = require('@hanzochat/api');
|
||||
const { getLogStores } = require('~/cache');
|
||||
const { batchResetMeiliFlags } = require('./utils');
|
||||
|
||||
@@ -32,7 +32,7 @@ const originalMessageModel = mongoose.models.Message;
|
||||
const originalConversationModel = mongoose.models.Conversation;
|
||||
|
||||
// Mock external modules
|
||||
jest.mock('@hanzochat/data-schemas', () => ({
|
||||
jest.mock('@librechat/data-schemas', () => ({
|
||||
logger: mockLogger,
|
||||
}));
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
const mongoose = require('mongoose');
|
||||
const { createModels } = require('@hanzochat/data-schemas');
|
||||
const { createModels } = require('@librechat/data-schemas');
|
||||
const models = createModels(mongoose);
|
||||
|
||||
module.exports = { ...models };
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
|
||||
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
|
||||
@@ -392,7 +392,7 @@ describe('batchResetMeiliFlags', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
// Mock logger.warn to track warning calls
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
warnSpy = jest.spyOn(logger, 'warn').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"keep": {
|
||||
"days": true,
|
||||
"amount": 14
|
||||
},
|
||||
"auditLog": "/Users/z/work/hanzo/chat/api/logs/.124163c776d287793643ac0e08ac1d35d67ad894-audit.json",
|
||||
"files": [
|
||||
{
|
||||
"date": 1771557162318,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/meiliSync-2026-02-19.log",
|
||||
"hash": "a54018af15e4552979b0e91a2379ef40b95019fe56fe70074bb13f91952d908f"
|
||||
}
|
||||
],
|
||||
"hashType": "sha256"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"keep": {
|
||||
"days": true,
|
||||
"amount": 14
|
||||
},
|
||||
"auditLog": "/Users/z/work/hanzo/chat/api/logs/.35252977fe148e605b7b92f19cd71e590a6f0a53-audit.json",
|
||||
"files": [
|
||||
{
|
||||
"date": 1771557162297,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/error-2026-02-19.log",
|
||||
"hash": "63688154da6c0a28cba1e30ddeef3eb867682460096d9b007dcfd2ddc25202b0"
|
||||
}
|
||||
],
|
||||
"hashType": "sha256"
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"keep": {
|
||||
"days": true,
|
||||
"amount": 14
|
||||
},
|
||||
"auditLog": "/Users/z/work/hanzo/chat/api/logs/.5a07238e142f72f47174c381d68b979f0f4a60b3-audit.json",
|
||||
"files": [
|
||||
{
|
||||
"date": 1750474453457,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/debug-2025-06-20.log",
|
||||
"hash": "696c5dfed20dbc87cd7113adb058ad5df3e53b93b9fc24840b7e236724ac4823"
|
||||
},
|
||||
{
|
||||
"date": 1750715218180,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/debug-2025-06-23.log",
|
||||
"hash": "c802b606c51329d1d65fe6c877dff02200e4d57e6565de3697ce4d8938bd8366"
|
||||
},
|
||||
{
|
||||
"date": 1750883760400,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/debug-2025-06-25.log",
|
||||
"hash": "202106c1ae63bd10f256f9249f6f32e20e495b9ca7f5ab7844f6dff28716805a"
|
||||
},
|
||||
{
|
||||
"date": 1750950599470,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/debug-2025-06-26.log",
|
||||
"hash": "e5f73d742f92938cef296a5c97cf8bb7f4e3db0198b8bc53bb0eee3ddf0f1e84"
|
||||
},
|
||||
{
|
||||
"date": 1751049961804,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/debug-2025-06-27.log",
|
||||
"hash": "15a471f383c1ea303252a3b35f88e44cc4bd1905666617dc9afc4b415d3ddac9"
|
||||
},
|
||||
{
|
||||
"date": 1751124937592,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/debug-2025-06-28.log",
|
||||
"hash": "77a7dd41fff34914a5ce25239c9fd77fafb8c3617a7a118550af69fbcc577643"
|
||||
},
|
||||
{
|
||||
"date": 1751599940774,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/debug-2025-07-03.log",
|
||||
"hash": "c86e337d49f3edad24952270eb6bebba4588201f1e14eab31b2482ee0c68be00"
|
||||
}
|
||||
],
|
||||
"hashType": "sha256"
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"keep": {
|
||||
"days": true,
|
||||
"amount": 14
|
||||
},
|
||||
"auditLog": "/Users/z/work/hanzo/chat/api/logs/.b5a17c43715e8a0a84a729c6012dc1ba16b1828b-audit.json",
|
||||
"files": [
|
||||
{
|
||||
"date": 1750954055845,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/meiliSync-2025-06-26.log",
|
||||
"hash": "980f8267840afde6278855f4218760f010a3fb215aa86ef5bb69dc08bb4b1b50"
|
||||
},
|
||||
{
|
||||
"date": 1751049961800,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/meiliSync-2025-06-27.log",
|
||||
"hash": "cebe79495cabf77d359dbcd3168502d3a5c4d8993e1bed0663fa40d850ccf6d5"
|
||||
},
|
||||
{
|
||||
"date": 1751124937590,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/meiliSync-2025-06-28.log",
|
||||
"hash": "bb29a81af67a7fce02315648194ef210ef2ad3c89e7083220d9a63103dc762cc"
|
||||
},
|
||||
{
|
||||
"date": 1751599940771,
|
||||
"name": "/Users/z/work/hanzo/chat/api/logs/meiliSync-2025-07-03.log",
|
||||
"hash": "9b454a63526db0eb56a27269fd38a86ac3d35dba85338ae89c91ea9895d467cb"
|
||||
}
|
||||
],
|
||||
"hashType": "sha256"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
2025-06-25T20:37:18.651Z info: [Optional] Redis not initialized.
|
||||
2025-06-25T20:37:20.168Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-25T20:39:50.405Z info: [Optional] Redis not initialized.
|
||||
2025-06-25T20:39:51.070Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-25T20:40:07.114Z info: [Optional] Redis not initialized.
|
||||
2025-06-25T20:40:07.770Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-25T20:40:53.234Z info: [Optional] Redis not initialized.
|
||||
2025-06-25T20:40:53.905Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
@@ -0,0 +1,115 @@
|
||||
2025-06-26T15:10:34.209Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T15:10:35.166Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T16:21:35.171Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T16:21:36.574Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T16:22:06.626Z error: connect ECONNREFUSED 127.0.0.1:27017
|
||||
2025-06-26T16:23:03.561Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T16:23:04.255Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T16:23:04.300Z info: Connected to MongoDB
|
||||
2025-06-26T16:23:04.301Z info: [indexSync] Starting index synchronization check...
|
||||
2025-06-26T16:23:04.420Z error: Invalid custom config file at /Users/z/work/hanzo/chat/chat.yaml:
|
||||
{
|
||||
"issues": [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"ag... [truncated]
|
||||
2025-06-26T16:23:04.420Z debug: Web search serperApiKey: Using environment variable SERPER_API_KEY (not set in environment, user provided value)
|
||||
2025-06-26T16:23:04.420Z debug: Web search firecrawlApiKey: Using environment variable FIRECRAWL_API_KEY (not set in environment, user provided value)
|
||||
2025-06-26T16:23:04.420Z debug: Web search firecrawlApiUrl: Using environment variable FIRECRAWL_API_URL (not set in environment, user provided value)
|
||||
2025-06-26T16:23:04.421Z debug: Web search jinaApiKey: Using environment variable JINA_API_KEY (not set in environment, user provided value)
|
||||
2025-06-26T16:23:04.421Z debug: Web search cohereApiKey: Using environment variable COHERE_API_KEY (not set in environment, user provided value)
|
||||
2025-06-26T16:23:04.421Z warn: Default value for CREDS_KEY is being used.
|
||||
2025-06-26T16:23:04.421Z warn: Default value for CREDS_IV is being used.
|
||||
2025-06-26T16:23:04.421Z warn: Default value for JWT_SECRET is being used.
|
||||
2025-06-26T16:23:04.421Z warn: Default value for JWT_REFRESH_SECRET is being used.
|
||||
2025-06-26T16:23:04.421Z info: Please replace any default secret values.
|
||||
2025-06-26T16:23:04.421Z info:
|
||||
|
||||
For your convenience, use this tool to generate your own secret values:
|
||||
https://www.hanzo.ai/toolkit/creds_generator
|
||||
|
||||
|
||||
2025-06-26T16:23:04.421Z warn: RAG API is either not running or not reachable at undefined, you may experience errors with file uploads.
|
||||
2025-06-26T16:23:04.429Z info: No changes needed for 'USER' role permissions
|
||||
2025-06-26T16:23:04.431Z info: No changes needed for 'ADMIN' role permissions
|
||||
2025-06-26T16:23:04.431Z info: Turnstile is DISABLED (no siteKey provided).
|
||||
2025-06-26T16:24:16.068Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T16:24:17.688Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T16:24:17.756Z info: Connected to MongoDB
|
||||
2025-06-26T16:24:17.757Z info: [indexSync] Starting index synchronization check...
|
||||
2025-06-26T16:24:17.811Z error: Invalid custom config file at /Users/z/work/hanzo/chat/chat.yaml:
|
||||
{
|
||||
"issues": [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"ag... [truncated]
|
||||
2025-06-26T16:24:17.812Z debug: Web search serperApiKey: Using environment variable SERPER_API_KEY (not set in environment, user provided value)
|
||||
2025-06-26T16:24:17.812Z debug: Web search firecrawlApiKey: Using environment variable FIRECRAWL_API_KEY (not set in environment, user provided value)
|
||||
2025-06-26T16:24:17.812Z debug: Web search firecrawlApiUrl: Using environment variable FIRECRAWL_API_URL (not set in environment, user provided value)
|
||||
2025-06-26T16:24:17.812Z debug: Web search jinaApiKey: Using environment variable JINA_API_KEY (not set in environment, user provided value)
|
||||
2025-06-26T16:24:17.812Z debug: Web search cohereApiKey: Using environment variable COHERE_API_KEY (not set in environment, user provided value)
|
||||
2025-06-26T16:24:17.812Z warn: Default value for CREDS_KEY is being used.
|
||||
2025-06-26T16:24:17.812Z warn: Default value for CREDS_IV is being used.
|
||||
2025-06-26T16:24:17.812Z warn: Default value for JWT_SECRET is being used.
|
||||
2025-06-26T16:24:17.812Z warn: Default value for JWT_REFRESH_SECRET is being used.
|
||||
2025-06-26T16:24:17.812Z info: Please replace any default secret values.
|
||||
2025-06-26T16:24:17.812Z info:
|
||||
|
||||
For your convenience, use this tool to generate your own secret values:
|
||||
https://www.hanzo.ai/toolkit/creds_generator
|
||||
|
||||
|
||||
2025-06-26T16:24:17.812Z warn: RAG API is either not running or not reachable at undefined, you may experience errors with file uploads.
|
||||
2025-06-26T16:24:17.823Z info: No changes needed for 'USER' role permissions
|
||||
2025-06-26T16:24:17.825Z info: No changes needed for 'ADMIN' role permissions
|
||||
2025-06-26T16:24:17.825Z info: Turnstile is DISABLED (no siteKey provided).
|
||||
2025-06-26T16:24:17.832Z info: Server listening at http://localhost:3080
|
||||
2025-06-26T16:24:18.010Z debug: [MEILI_SYNC:meili-index-sync] Creating initial flow state
|
||||
2025-06-26T16:24:18.020Z info: [indexSync] Messages are fully synced: 0/0
|
||||
2025-06-26T16:24:18.023Z info: [indexSync] Conversations are fully synced: 0/0
|
||||
2025-06-26T16:24:18.024Z debug: [indexSync] No sync was needed
|
||||
2025-06-26T16:24:37.105Z error: invalid signature
|
||||
2025-06-26T17:16:21.631Z info: Cleaning up FlowStateManager intervals...
|
||||
2025-06-26T17:28:31.428Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T19:16:07.812Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T19:16:09.408Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T19:16:39.465Z error: connect ECONNREFUSED 127.0.0.1:27017
|
||||
2025-06-26T19:28:57.619Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T19:28:58.798Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:18:29.425Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:18:30.678Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:19:00.734Z error: getaddrinfo ENOTFOUND mongodb
|
||||
2025-06-26T21:20:04.085Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:20:04.788Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:20:34.832Z error: connect ECONNREFUSED ::1:27017, connect ECONNREFUSED 127.0.0.1:27017
|
||||
2025-06-26T21:35:21.338Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:35:22.746Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:35:52.803Z error: connect ECONNREFUSED ::1:27017, connect ECONNREFUSED 127.0.0.1:27017
|
||||
2025-06-26T21:39:16.497Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:39:17.655Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:39:47.696Z error: connect ECONNREFUSED ::1:27017, connect ECONNREFUSED 127.0.0.1:27017
|
||||
2025-06-26T21:43:04.982Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:43:06.587Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:43:07.208Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:43:07.990Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:43:09.790Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:43:10.572Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:43:12.993Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:43:14.084Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:43:16.627Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:43:17.383Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:43:19.449Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:43:20.212Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:43:34.812Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:43:36.179Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-26T21:43:50.258Z error: connect ECONNREFUSED ::1:27017, connect ECONNREFUSED 127.0.0.1:27017
|
||||
2025-06-26T21:44:17.565Z info: [Optional] Redis not initialized.
|
||||
2025-06-26T21:44:18.322Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-27T03:16:07.463Z info: [Optional] Redis not initialized.
|
||||
2025-06-27T03:16:08.973Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-27T03:16:17.650Z debug: [indexSync] Clearing sync timeouts before exiting...
|
||||
2025-06-27T03:19:09.423Z info: [Optional] Redis not initialized.
|
||||
2025-06-27T03:19:10.741Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-27T03:19:15.742Z debug: [indexSync] Clearing sync timeouts before exiting...
|
||||
@@ -0,0 +1,3 @@
|
||||
2025-06-27T18:46:02.321Z info: [Optional] Redis not initialized.
|
||||
2025-06-27T18:46:03.818Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-27T18:46:23.237Z debug: [indexSync] Clearing sync timeouts before exiting...
|
||||
@@ -0,0 +1,3 @@
|
||||
2025-06-28T15:35:37.951Z info: [Optional] Redis not initialized.
|
||||
2025-06-28T15:35:39.502Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-06-28T15:36:09.559Z error: connect ECONNREFUSED ::1:27017, connect ECONNREFUSED 127.0.0.1:27017
|
||||
@@ -0,0 +1,3 @@
|
||||
2025-07-04T03:32:21.282Z info: [Optional] Redis not initialized.
|
||||
2025-07-04T03:32:22.739Z info: [Optional] IoRedis not initialized for rate limiters.
|
||||
2025-07-04T03:32:40.543Z debug: [indexSync] Clearing sync timeouts before exiting...
|
||||
@@ -0,0 +1,4 @@
|
||||
{"level":"error","message":"[mongoMeili] Error checking index convos: fetch failed","name":"MeiliSearchCommunicationError","stack":"MeiliSearchCommunicationError: fetch failed\n at node:internal/deps/undici/undici:13510:13\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)"}
|
||||
{"level":"error","message":"[mongoMeili] Error checking index messages: fetch failed","name":"MeiliSearchCommunicationError","stack":"MeiliSearchCommunicationError: fetch failed\n at node:internal/deps/undici/undici:13510:13\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)"}
|
||||
{"level":"error","message":"[mongoMeili] Error checking index convos: fetch failed","name":"MeiliSearchCommunicationError","stack":"MeiliSearchCommunicationError: fetch failed\n at node:internal/deps/undici/undici:13510:13\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)"}
|
||||
{"level":"error","message":"[mongoMeili] Error checking index messages: fetch failed","name":"MeiliSearchCommunicationError","stack":"MeiliSearchCommunicationError: fetch failed\n at node:internal/deps/undici/undici:13510:13\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)"}
|
||||
@@ -0,0 +1,4 @@
|
||||
{"level":"debug","message":"[mongoMeili] Index convos already exists"}
|
||||
{"level":"debug","message":"[mongoMeili] Index convos already exists"}
|
||||
{"level":"debug","message":"[mongoMeili] Index messages already exists"}
|
||||
{"level":"debug","message":"[mongoMeili] Index messages already exists"}
|
||||
@@ -0,0 +1,4 @@
|
||||
{"level":"debug","message":"[mongoMeili] Index messages already exists"}
|
||||
{"level":"debug","message":"[mongoMeili] Index convos already exists"}
|
||||
{"level":"debug","message":"[mongoMeili] Index messages already exists"}
|
||||
{"level":"debug","message":"[mongoMeili] Index convos already exists"}
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
const mongoose = require('mongoose');
|
||||
const crypto = require('node:crypto');
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { getCustomEndpointConfig } = require('@hanzochat/api');
|
||||
const {
|
||||
Tools,
|
||||
@@ -10,8 +10,8 @@ const {
|
||||
isAgentsEndpoint,
|
||||
isEphemeralAgentId,
|
||||
encodeEphemeralAgentId,
|
||||
} = require('@hanzochat/data-provider');
|
||||
const { mcp_all, mcp_delimiter } = require('@hanzochat/data-provider').Constants;
|
||||
} = require('librechat-data-provider');
|
||||
const { mcp_all, mcp_delimiter } = require('librechat-data-provider').Constants;
|
||||
const {
|
||||
removeAgentFromAllProjects,
|
||||
removeAgentIdsFromProject,
|
||||
@@ -96,7 +96,7 @@ const getAgents = async (searchParameter) => await Agent.find(searchParameter).l
|
||||
* @param {string} params.spec
|
||||
* @param {string} params.agent_id
|
||||
* @param {string} params.endpoint
|
||||
* @param {import('@hanzochat/agents').ClientOptions} [params.model_parameters]
|
||||
* @param {import('@librechat/agents').ClientOptions} [params.model_parameters]
|
||||
* @returns {Promise<Agent|null>} The agent document as a plain object, or null if not found.
|
||||
*/
|
||||
const loadEphemeralAgent = async ({ req, spec, endpoint, model_parameters: _m }) => {
|
||||
@@ -189,7 +189,7 @@ const loadEphemeralAgent = async ({ req, spec, endpoint, model_parameters: _m })
|
||||
* @param {string} params.spec
|
||||
* @param {string} params.agent_id
|
||||
* @param {string} params.endpoint
|
||||
* @param {import('@hanzochat/agents').ClientOptions} [params.model_parameters]
|
||||
* @param {import('@librechat/agents').ClientOptions} [params.model_parameters]
|
||||
* @returns {Promise<Agent|null>} The agent document as a plain object, or null if not found.
|
||||
*/
|
||||
const loadAgent = async ({ req, spec, agent_id, endpoint, model_parameters }) => {
|
||||
|
||||
+17
-17
@@ -13,9 +13,9 @@ jest.mock('~/server/services/Config', () => ({
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const { agentSchema } = require('@hanzochat/data-schemas');
|
||||
const { agentSchema } = require('@librechat/data-schemas');
|
||||
const { MongoMemoryServer } = require('mongodb-memory-server');
|
||||
const { AccessRoleIds, ResourceType, PrincipalType } = require('@hanzochat/data-provider');
|
||||
const { AccessRoleIds, ResourceType, PrincipalType } = require('librechat-data-provider');
|
||||
const {
|
||||
getAgent,
|
||||
loadAgent,
|
||||
@@ -35,7 +35,7 @@ const { getCachedTools, getMCPServerTools } = require('~/server/services/Config'
|
||||
const { AclEntry, User } = require('~/db/models');
|
||||
|
||||
/**
|
||||
* @type {import('mongoose').Model<import('@hanzochat/data-schemas').IAgent>}
|
||||
* @type {import('mongoose').Model<import('@librechat/data-schemas').IAgent>}
|
||||
*/
|
||||
let Agent;
|
||||
|
||||
@@ -1111,7 +1111,7 @@ describe('models/Agent', () => {
|
||||
const agentId = 'ephemeral_test';
|
||||
const endpoint = 'openai';
|
||||
|
||||
const originalModule = jest.requireActual('@hanzochat/data-provider');
|
||||
const originalModule = jest.requireActual('librechat-data-provider');
|
||||
|
||||
const mockDataProvider = {
|
||||
...originalModule,
|
||||
@@ -1121,12 +1121,12 @@ describe('models/Agent', () => {
|
||||
},
|
||||
};
|
||||
|
||||
jest.doMock('@hanzochat/data-provider', () => mockDataProvider);
|
||||
jest.doMock('librechat-data-provider', () => mockDataProvider);
|
||||
|
||||
expect(agentId).toBeDefined();
|
||||
expect(endpoint).toBeDefined();
|
||||
|
||||
jest.dontMock('@hanzochat/data-provider');
|
||||
jest.dontMock('librechat-data-provider');
|
||||
});
|
||||
|
||||
test('should handle loadAgent functionality and errors', async () => {
|
||||
@@ -2189,13 +2189,13 @@ describe('models/Agent', () => {
|
||||
const actions = [
|
||||
{
|
||||
action_id: '123',
|
||||
metadata: { version: '1.0', endpoints: ['GET /v1/chat/test'], schema: { type: 'object' } },
|
||||
metadata: { version: '1.0', endpoints: ['GET /api/test'], schema: { type: 'object' } },
|
||||
},
|
||||
{
|
||||
action_id: '456',
|
||||
metadata: {
|
||||
version: '2.0',
|
||||
endpoints: ['POST /v1/chat/example'],
|
||||
endpoints: ['POST /api/example'],
|
||||
schema: { type: 'string' },
|
||||
},
|
||||
},
|
||||
@@ -2212,10 +2212,10 @@ describe('models/Agent', () => {
|
||||
test('should generate different hashes for different action metadata', async () => {
|
||||
const actionIds = ['test.com_action_123'];
|
||||
const actions1 = [
|
||||
{ action_id: '123', metadata: { version: '1.0', endpoints: ['GET /v1/chat/test'] } },
|
||||
{ action_id: '123', metadata: { version: '1.0', endpoints: ['GET /api/test'] } },
|
||||
];
|
||||
const actions2 = [
|
||||
{ action_id: '123', metadata: { version: '2.0', endpoints: ['GET /v1/chat/test'] } },
|
||||
{ action_id: '123', metadata: { version: '2.0', endpoints: ['GET /api/test'] } },
|
||||
];
|
||||
|
||||
const hash1 = await generateActionMetadataHash(actionIds, actions1);
|
||||
@@ -2284,8 +2284,8 @@ describe('models/Agent', () => {
|
||||
},
|
||||
},
|
||||
endpoints: [
|
||||
{ path: '/v1/chat/test', method: 'GET', params: ['id'] },
|
||||
{ path: '/v1/chat/create', method: 'POST', body: true },
|
||||
{ path: '/api/test', method: 'GET', params: ['id'] },
|
||||
{ path: '/api/create', method: 'POST', body: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -2391,7 +2391,7 @@ describe('models/Agent', () => {
|
||||
});
|
||||
|
||||
test('should test ephemeral agent loading logic', async () => {
|
||||
const { EPHEMERAL_AGENT_ID } = require('@hanzochat/data-provider').Constants;
|
||||
const { EPHEMERAL_AGENT_ID } = require('librechat-data-provider').Constants;
|
||||
|
||||
getCachedTools.mockResolvedValue({
|
||||
tool1_mcp_server1: {},
|
||||
@@ -2514,7 +2514,7 @@ describe('models/Agent', () => {
|
||||
});
|
||||
|
||||
test('should handle ephemeral agent with no MCP servers', async () => {
|
||||
const { EPHEMERAL_AGENT_ID } = require('@hanzochat/data-provider').Constants;
|
||||
const { EPHEMERAL_AGENT_ID } = require('librechat-data-provider').Constants;
|
||||
|
||||
getCachedTools.mockResolvedValue({});
|
||||
|
||||
@@ -2546,7 +2546,7 @@ describe('models/Agent', () => {
|
||||
});
|
||||
|
||||
test('should handle ephemeral agent with undefined ephemeralAgent in body', async () => {
|
||||
const { EPHEMERAL_AGENT_ID } = require('@hanzochat/data-provider').Constants;
|
||||
const { EPHEMERAL_AGENT_ID } = require('librechat-data-provider').Constants;
|
||||
|
||||
getCachedTools.mockResolvedValue({});
|
||||
|
||||
@@ -2584,7 +2584,7 @@ describe('models/Agent', () => {
|
||||
});
|
||||
|
||||
test('should handle ephemeral agent with extremely large tool list', async () => {
|
||||
const { EPHEMERAL_AGENT_ID } = require('@hanzochat/data-provider').Constants;
|
||||
const { EPHEMERAL_AGENT_ID } = require('librechat-data-provider').Constants;
|
||||
|
||||
const largeToolList = Array.from({ length: 100 }, (_, i) => `tool_${i}_mcp_server1`);
|
||||
const availableTools = largeToolList.reduce((acc, tool) => {
|
||||
@@ -3123,7 +3123,7 @@ describe('models/Agent', () => {
|
||||
});
|
||||
|
||||
test('should handle loadEphemeralAgent with malformed MCP tool names', async () => {
|
||||
const { EPHEMERAL_AGENT_ID } = require('@hanzochat/data-provider').Constants;
|
||||
const { EPHEMERAL_AGENT_ID } = require('librechat-data-provider').Constants;
|
||||
|
||||
getCachedTools.mockResolvedValue({
|
||||
malformed_tool_name: {}, // No mcp delimiter
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { Banner } = require('~/db/models');
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
|
||||
const options = [
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { createTempChatExpirationDate } = require('@hanzochat/api');
|
||||
const { getMessages, deleteMessages } = require('./Message');
|
||||
const { Conversation } = require('~/db/models');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const mongoose = require('mongoose');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const { EModelEndpoint } = require('@hanzochat/data-provider');
|
||||
const { EModelEndpoint } = require('librechat-data-provider');
|
||||
const { MongoMemoryServer } = require('mongodb-memory-server');
|
||||
const {
|
||||
deleteNullOrEmptyConversations,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { ConversationTag, Conversation } = require('~/db/models');
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
const { logger } = require('@hanzochat/data-schemas');
|
||||
const { EToolResources, FileContext } = require('@hanzochat/data-provider');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { EToolResources, FileContext } = require('librechat-data-provider');
|
||||
const { File } = require('~/db/models');
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
const mongoose = require('mongoose');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const { MongoMemoryServer } = require('mongodb-memory-server');
|
||||
const { createModels, createMethods } = require('@hanzochat/data-schemas');
|
||||
const { createModels, createMethods } = require('@librechat/data-schemas');
|
||||
const {
|
||||
SystemRoles,
|
||||
ResourceType,
|
||||
AccessRoleIds,
|
||||
PrincipalType,
|
||||
} = require('@hanzochat/data-provider');
|
||||
} = require('librechat-data-provider');
|
||||
const { grantPermission } = require('~/server/services/PermissionService');
|
||||
const { createAgent } = require('./Agent');
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user