diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 1999628e..97dce918 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -12,7 +12,7 @@ body: id: version attributes: label: What version of eigent are you using? - placeholder: E.g., 0.0.80 + placeholder: E.g., 0.0.81 validations: required: true diff --git a/.github/workflows/build-view.yml b/.github/workflows/build-view.yml index 0a3469ad..f5190e39 100644 --- a/.github/workflows/build-view.yml +++ b/.github/workflows/build-view.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: include: - - os: [self-hosted, macOS, ARM64] + - os: macos-latest arch: arm64 artifact_name: macos-arm64 - os: windows-latest @@ -85,7 +85,13 @@ jobs: - name: Build Release Files (macOS with signing) if: runner.os == 'macOS' timeout-minutes: 90 - run: npm run build -- --arch ${{ matrix.arch }} + run: | + # Increase file descriptor limit to prevent EMFILE errors during signing + # This is needed because electron-builder signs all files recursively, + # and Python venvs contain thousands of files + ulimit -n 65536 || ulimit -n 10240 + echo "File descriptor limit set to: $(ulimit -n)" + npm run build -- --arch ${{ matrix.arch }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CSC_LINK: ${{ secrets.CERT_P12 }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 136ffa2c..2f5b8a15 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -92,7 +92,11 @@ jobs: # Step for macOS builds with signing - name: Build Release Files (macOS with signing) if: runner.os == 'macOS' - run: npm run build -- --arch ${{ matrix.arch }} + run: | + # Increase file descriptor limit to prevent EMFILE errors during signing + ulimit -n 65536 || ulimit -n 10240 + echo "File descriptor limit set to: $(ulimit -n)" + npm run build -- --arch ${{ matrix.arch }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CSC_LINK: ${{ secrets.CERT_P12 }} diff --git a/README.md b/README.md index d244627b..ac00ad25 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@
-**Eigent** is the open source cowork desktop application, empowering you to build, manage, and deploy a custom AI workforce that can turn your most complex workflows into automated tasks. +**Eigent** is the open source Cowork desktop application, empowering you to build, manage, and deploy a custom AI workforce that can turn your most complex workflows into automated tasks. As a leading open-source Cowork product, Eigent brings together the best of open-source collaboration and AI-powered automation. Built on [CAMEL-AI][camel-site]'s acclaimed open-source project, our system introduces a **Multi-Agent Workforce** that **boosts productivity** through parallel execution, customization, and privacy protection. @@ -51,23 +51,23 @@ Built on [CAMEL-AI][camel-site]'s acclaimed open-source project, our system intr #### TOC -- [🚀 Getting Started](#-getting-started) +- [🚀 Getting Started with Open Source Cowork](#-getting-started-with-open-source-Cowork) - [🏠 Local Deployment (Recommended)](#-local-deployment-recommended) - [⚡ Quick Start (Cloud-Connected)](#-quick-start-cloud-connected) - [🏢 Enterprise](#-enterprise) - [☁️ Cloud Version](#️-cloud-version) -- [✨ Key features](#-key-features) +- [✨ Key features - Open Source Cowork](#-key-features---open-source-Cowork) - [🏭 Workforce](#-workforce) - [🧠 Comprehensive Model Support](#-comprehensive-model-support) - [🔌 MCP Tools Integration (MCP)](#-mcp-tools-integration-mcp) - [✋ Human-in-the-Loop](#-human-in-the-loop) - [👐 100% Open Source](#-100-open-source) -- [🧩 Use Cases](#-use-cases) +- [🧩 Use Cases - Open Source Cowork](#-use-cases---open-source-Cowork) - [🛠️ Tech Stack](#-tech-stack) - [Backend](#backend) - [Frontend](#frontend) -- [🌟 Staying ahead](#staying-ahead) -- [🗺️ Roadmap](#-roadmap) +- [🌟 Staying ahead - Open Source Cowork](#-staying-ahead---open-source-Cowork) +- [🗺️ Roadmap - Open Source Cowork](#️-roadmap---open-source-Cowork) - [📖 Contributing](#-contributing) - [Main Contributors](#main-contributors) - [Distinguished amabssador](#distinguished-amabssador) @@ -81,7 +81,7 @@ Built on [CAMEL-AI][camel-site]'s acclaimed open-source project, our system intr -## **🚀 Getting Started** +## **🚀 Getting Started with Open Source Cowork** > **🔓 Build in Public** — Eigent is **100% open source** from day one. Every feature, every commit, every decision is transparent. We believe the best AI tools should be built openly with the community, not behind closed doors. @@ -155,11 +155,11 @@ For teams who prefer managed infrastructure, we also offer a cloud platform. The Get started at Eigent.ai → -## **✨ Key features** -Unlock the full potential of exceptional productivity with Eigent’s powerful features—built for seamless integration, smarter task execution, and boundless automation. +## **✨ Key features - Open Source Cowork** +Unlock the full potential of exceptional productivity with Eigent's open-source Cowork powerful features — built for seamless integration, smarter task execution, and boundless automation. ### 🏭 Workforce -Employs a team of specialized AI agents that collaborate to solve complex tasks. Eigent dynamically breaks down tasks and activates multiple agents to work **in parallel.** +Employs a team of specialized AI agents that collaborate to solve complex tasks. Eigent's open-source Cowork dynamically breaks down tasks and activates multiple agents to work **in parallel.** Eigent pre-defined the following agent workers: @@ -173,7 +173,7 @@ Eigent pre-defined the following agent workers:
### 🧠 Comprehensive Model Support -Deploy Eigent locally with your preferred models. +Deploy the Eigent open-source Cowork desktop locally with your preferred models. ![Model](https://eigent-ai.github.io/.github/assets/gif/feature_local_model.gif) @@ -200,7 +200,9 @@ Eigent is completely open-sourced. You can download, inspect, and modify the cod
-## 🧩 Use Cases +## 🧩 Use Cases - Open Source Cowork + +Discover how developers worldwide leverage Eigent's open-source Cowork capabilities to automate complex workflows and boost productivity across diverse industries. ### 1. Palm Springs Tennis Trip Itinerary with Slack Summary [Replay ▶️](https://www.eigent.ai/download?share_token=IjE3NTM0MzUxNTEzMzctNzExMyI.aIeysw.MUeG6ZcBxI1GqvPDvn4dcv-CDWw__1753435151337-7113) @@ -279,6 +281,8 @@ Please add this signature image to the Signature Areas in the PDF. You could ins ## 🛠️ Tech Stack +Eigent open-source Cowork desktop is built on modern, reliable technologies that ensure scalability, performance, and extensibility. + ### Backend - **Framework:** FastAPI - **Package Manager:** uv @@ -295,7 +299,7 @@ Please add this signature image to the Signature Areas in the PDF. You could ins - **State Management:** Zustand - **Flow Editor:** React Flow -## 🌟 Staying ahead +## 🌟 Staying ahead - Open Source Cowork > \[!IMPORTANT] > @@ -303,7 +307,9 @@ Please add this signature image to the Signature Areas in the PDF. You could ins ![][image-star-us] -## 🗺️ Roadmap +## 🗺️ Roadmap - Open Source Cowork + +Our open-source Cowork continues to evolve with input from the community. Here's what's coming next: | Topics | Issues | Discord Channel | | ------------------------ | -- |-- | diff --git a/README_CN.md b/README_CN.md index 1bd95f97..2ff0c917 100644 --- a/README_CN.md +++ b/README_CN.md @@ -28,7 +28,7 @@
-**Eigent** 是全球首个 **多智能体工作流** 桌面应用程序,帮助您构建、管理和部署定制化的 AI 工作团队,将最复杂的工作流程转化为自动化任务。 +**Eigent** 是全球首个 **多智能体工作流** 桌面应用程序,帮助您构建、管理和部署定制化的 AI 工作团队,将最复杂的工作流程转化为自动化任务。作为领先的开源 Cowork产品,Eigent融合了开源 Cowork 和AI驱动自动化的优势。 基于 [CAMEL-AI][camel-site] 广受赞誉的开源项目,我们的系统引入了 **多智能体工作流**,通过并行执行、定制化和隐私保护 **提升生产力**。 @@ -51,22 +51,22 @@ #### 目录 -- [🚀 快速开始](#-快速开始) +- [🚀 快速开始 - 开源 Cowork](#-快速开始---开源 Cowork) - [☁️ 云版本](#️-云版本) - [🏠 自托管(社区版)](#-自托管社区版) - [🏢 企业版](#-企业版) -- [✨ 核心功能](#-核心功能) +- [✨ 核心功能 - 开源 Cowork](#-核心功能---开源 Cowork) - [🏭 工作流](#-工作流) - [🧠 全面模型支持](#-全面模型支持) - [🔌 MCP 工具集成](#-mcp-工具集成) - [✋ 人工介入](#-人工介入) - [👐 100% 开源](#-100-开源) -- [🧩 使用案例](#-使用案例) +- [🧩 使用案例 - 开源 Cowork](#-使用案例---开源 Cowork) - [🛠️ 技术栈](#️-技术栈) - [后端](#后端) - [前端](#前端) -- [🌟 保持领先](#保持领先) -- [🗺️ 路线图](#️-路线图) +- [🌟 保持领先 - 开源 Cowork](#保持领先---开源 Cowork) +- [🗺️ 路线图 - 开源 Cowork](#️-路线图---开源 Cowork) - [📖 贡献](#-贡献) - [核心贡献者](#核心贡献者) - [杰出大使](#杰出大使) @@ -80,7 +80,7 @@ -## **🚀 快速开始** +## **🚀 快速开始 - 开源 Cowork** 有三种方式开始使用 Eigent: @@ -148,11 +148,11 @@ uv sync 📧 更多详情,请联系 [info@eigent.ai](mailto:info@eigent.ai)。 -## **✨ 核心功能** -通过 Eigent 的强大功能释放卓越生产力的全部潜力——专为无缝集成、智能任务执行和无边界自动化而设计。 +## **✨ 核心功能 - 开源 Cowork** +通过 Eigent 开源 Cowork的强大功能释放卓越生产力的全部潜力——专为无缝集成、智能任务执行和无边界自动化而设计。 -### 🏭 工作流 -部署一支专业 AI 智能体团队,协作解决复杂任务。Eigent 动态分解任务并激活多个智能体 **并行工作**。 +### 🏭 工作流 +部署一支专业 AI 智能体团队,协作解决复杂任务。Eigent 开源 Cowork动态分解任务并激活多个智能体 **并行工作**。 Eigent 预定义了以下智能体工作者: @@ -165,8 +165,8 @@ Eigent 预定义了以下智能体工作者:
-### 🧠 全面模型支持 -使用您偏好的模型本地部署 Eigent。 +### 🧠 全面模型支持 +使用您偏好的模型本地部署 Eigent 开源 Cowork桌面应用。 ![Model](https://eigent-ai.github.io/.github/assets/gif/feature_local_model.gif) @@ -193,7 +193,9 @@ Eigent 完全开源。您可以下载、检查和修改代码,确保透明度
-## 🧩 使用案例 +## 🧩 使用案例 - 开源 Cowork + +了解全球开发者如何利用 Eigent 的开源 Cowork能力,在各行各业自动化复杂工作流程并提升生产力。 ### 1. 棕榈泉网球旅行行程与 Slack 摘要 [回放 ▶️](https://www.eigent.ai/download?share_token=IjE3NTM0MzUxNTEzMzctNzExMyI.aIeysw.MUeG6ZcBxI1GqvPDvn4dcv-CDWw__1753435151337-7113) @@ -267,6 +269,8 @@ Eigent 完全开源。您可以下载、检查和修改代码,确保透明度 ## 🛠️ 技术栈 +Eigent 开源 Cowork桌面应用基于现代、可靠的技术构建,确保可扩展性、性能和可扩展性。 + ### 后端 - **框架:** FastAPI - **包管理器:** uv @@ -282,7 +286,7 @@ Eigent 完全开源。您可以下载、检查和修改代码,确保透明度 - **状态管理:** Zustand - **流程编辑器:** React Flow -## 🌟 保持领先 +## 🌟 保持领先 - 开源 Cowork > \[!重要] > @@ -290,7 +294,9 @@ Eigent 完全开源。您可以下载、检查和修改代码,确保透明度 ![][image-star-us] -## 🗺️ 路线图 +## 🗺️ 路线图 - 开源 Cowork + +我们的开源 Cowork将继续在社区的参与下发展。以下是接下来的计划: | 主题 | 问题 | Discord 频道 | | ------------------------ | -- |-- | @@ -304,7 +310,7 @@ Eigent 完全开源。您可以下载、检查和修改代码,确保透明度 ## [🤝 贡献][contribution-link] -我们相信通过开源协作建立信任。您的创意贡献将推动 `Eigent` 的创新。探索我们的 GitHub 问题与项目,加入我们 🤝❤️ [贡献指南][contribution-link] +我们相信通过开源 Cowork建立信任。您的创意贡献将推动 `Eigent` 的创新。探索我们的 GitHub 问题与项目,加入我们 🤝❤️ [贡献指南][contribution-link] ## Contributors diff --git a/README_JA.md b/README_JA.md index 92f887a8..fb9d34c7 100644 --- a/README_JA.md +++ b/README_JA.md @@ -28,7 +28,7 @@
-**Eigent**は、オープンソースのコワークデスクトップアプリケーションです。複雑なワークフローを自動化タスクに変換できるカスタムAIワークフォースを構築、管理、デプロイする力を提供します。 +**Eigent**は、オープンソースのコワークデスクトップアプリケーションです。複雑なワークフローを自動化タスクに変換できるカスタムAIワークフォースを構築、管理、デプロイする力を提供します。先進的なオープンソース Cowork製品として、EigentはオープンソースコラボレーションとAI駆動の自動化の最良の部分を組み合わせています。 [CAMEL-AI][camel-site]の評価の高いオープンソースプロジェクトを基盤として構築されており、**マルチエージェントワークフォース**を導入し、並列実行、カスタマイズ、プライバシー保護を通じて**生産性を向上**させます。 @@ -51,23 +51,23 @@ #### TOC -- [🚀 はじめに](#-はじめに) +- [🚀 はじめに - オープンソース Cowork](#-はじめに---オープンソース Cowork) - [🏠 ローカルデプロイメント(推奨)](#-ローカルデプロイメント推奨) - [⚡ クイックスタート(クラウド接続)](#-クイックスタートクラウド接続) - [🏢 エンタープライズ](#-エンタープライズ) - [☁️ クラウドバージョン](#️-クラウドバージョン) -- [✨ 主な機能](#-主な機能) +- [✨ 主な機能 - オープンソース Cowork](#-主な機能---オープンソース Cowork) - [🏭 ワークフォース](#-ワークフォース) - [🧠 包括的なモデルサポート](#-包括的なモデルサポート) - [🔌 MCPツール統合](#-mcpツール統合) - [✋ ヒューマンインザループ](#-ヒューマンインザループ) - [👐 100%オープンソース](#-100オープンソース) -- [🧩 ユースケース](#-ユースケース) +- [🧩 ユースケース - オープンソース Cowork](#-ユースケース---オープンソース Cowork) - [🛠️ 技術スタック](#️-技術スタック) - [バックエンド](#バックエンド) - [フロントエンド](#フロントエンド) -- [🌟 最新情報を入手](#最新情報を入手) -- [🗺️ ロードマップ](#️-ロードマップ) +- [🌟 最新情報を入手 - オープンソース Cowork](#最新情報を入手---オープンソース Cowork) +- [🗺️ ロードマップ - オープンソース Cowork](#️-ロードマップ---オープンソース Cowork) - [📖 コントリビューション](#-コントリビューション) - [エコシステム](#エコシステム) - [📄 オープンソースライセンス](#-オープンソースライセンス) @@ -79,7 +79,7 @@ -## **🚀 はじめに** +## **🚀 はじめに - オープンソース Cowork** > **🔓 オープンに開発** — Eigentは初日から**100%オープンソース**です。すべての機能、すべてのコミット、すべての決定が透明です。最高のAIツールは、閉じられたドアの後ろではなく、コミュニティと共にオープンに構築されるべきだと信じています。 @@ -153,11 +153,11 @@ uv sync Eigent.aiで始める → -## **✨ 主な機能** -Eigentの強力な機能で卓越した生産性の可能性を最大限に引き出しましょう — シームレスな統合、よりスマートなタスク実行、無限の自動化のために構築されています。 +## **✨ 主な機能 - オープンソース Cowork** +Eigentのオープンソース Coworkの強力な機能で卓越した生産性の可能性を最大限に引き出しましょう — シームレスな統合、よりスマートなタスク実行、無限の自動化のために構築されています。 ### 🏭 ワークフォース -複雑なタスクを解決するために協力する専門AIエージェントのチームを活用します。Eigentは動的にタスクを分解し、複数のエージェントを**並列で**動作させます。 +複雑なタスクを解決するために協力する専門AIエージェントのチームを活用します。Eigentのオープンソース Coworkは動的にタスクを分解し、複数のエージェントを**並列で**動作させます。 Eigentは以下のエージェントワーカーを事前定義しています: @@ -171,7 +171,7 @@ Eigentは以下のエージェントワーカーを事前定義しています
### 🧠 包括的なモデルサポート -お好みのモデルでEigentをローカルにデプロイできます。 +お好みのモデルでEigent オープンソース Coworkデスクトップをローカルにデプロイできます。 ![Model](https://eigent-ai.github.io/.github/assets/gif/feature_local_model.gif) @@ -198,7 +198,9 @@ Eigentは完全にオープンソースです。コードをダウンロード
-## 🧩 ユースケース +## 🧩 ユースケース - オープンソース Cowork + +世界中の開発者がEigentのオープンソース Cowork機能を活用して、さまざまな業界で複雑なワークフローを自動化し、生産性を向上させている方法をご覧ください。 ### 1. パームスプリングステニス旅行の旅程とSlackサマリー [リプレイ ▶️](https://www.eigent.ai/download?share_token=IjE3NTM0MzUxNTEzMzctNzExMyI.aIeysw.MUeG6ZcBxI1GqvPDvn4dcv-CDWw__1753435151337-7113) @@ -277,6 +279,8 @@ Documentsディレクトリにmydocsというフォルダがあります。ス ## 🛠️ 技術スタック +Eigent オープンソース Coworkデスクトップは、スケーラビリティ、パフォーマンス、拡張性を確保する最新の信頼性の高いテクノロジーで構築されています。 + ### バックエンド - **フレームワーク:** FastAPI - **パッケージマネージャー:** uv @@ -293,7 +297,7 @@ Documentsディレクトリにmydocsというフォルダがあります。ス - **状態管理:** Zustand - **フローエディター:** React Flow -## 🌟 最新情報を入手 +## 🌟 最新情報を入手 - オープンソース Cowork > \[!IMPORTANT] > @@ -301,7 +305,9 @@ Documentsディレクトリにmydocsというフォルダがあります。ス ![][image-star-us] -## 🗺️ ロードマップ +## 🗺️ ロードマップ - オープンソース Cowork + +私たちのオープンソース Coworkはコミュニティからのフィードバックを取り入れながら進化を続けています。次に予定されている内容は以下の通りです: | トピック | 課題 | Discordチャンネル | | ------------------------ | -- |-- | diff --git a/README_PT-BR.md b/README_PT-BR.md index 12aee44d..a6d4f152 100644 --- a/README_PT-BR.md +++ b/README_PT-BR.md @@ -28,7 +28,7 @@
-**Eigent** é a aplicação desktop cowork open source que capacita você a construir, gerenciar e implantar uma força de trabalho de IA personalizada, capaz de transformar seus fluxos de trabalho mais complexos em tarefas automatizadas. +**Eigent** é a aplicação desktop Cowork código aberto que capacita você a construir, gerenciar e implantar uma força de trabalho de IA personalizada, capaz de transformar seus fluxos de trabalho mais complexos em tarefas automatizadas. Como um produto líder de Cowork código aberto, o Eigent reúne o melhor da colaboração open source e da automação impulsionada por IA. Construído sobre o aclamado projeto open source da [CAMEL-AI][camel-site], nosso sistema introduz uma **Força de Trabalho Multiagente** que **aumenta a produtividade** por meio de execução paralela, personalização e proteção de privacidade. @@ -51,23 +51,23 @@ Construído sobre o aclamado projeto open source da [CAMEL-AI][camel-site], noss #### TOC -- [🚀 Primeiros Passos](#-primeiros-passos) +- [🚀 Primeiros Passos com Cowork Open Source](#-primeiros-passos-com-Cowork-open-source) - [🏠 Implantação Local (Recomendado)](#-implantação-local-recomendado) - [⚡ Início Rápido (Conectado à Nuvem)](#-início-rápido-conectado-à-nuvem) - [🏢 Empresarial](#-empresarial) - [☁️ Versão em Nuvem](#️-versão-em-nuvem) -- [✨ Principais Recursos](#-principais-recursos) +- [✨ Principais Recursos - Cowork Open Source](#-principais-recursos---Cowork-open-source) - [🏭 Força de Trabalho](#-força-de-trabalho) - [🧠 Suporte Abrangente a Modelos](#-suporte-abrangente-a-modelos) - [🔌 Integração de Ferramentas MCP (MCP)](#-integração-de-ferramentas-mcp-mcp) - [✋ Humano no Circuito](#-humano-no-circuito) - [👐 100% Código Aberto](#-100-código-aberto) -- [🧩 Casos de Uso](#-casos-de-uso) +- [🧩 Casos de Uso - Cowork Open Source](#-casos-de-uso---Cowork-open-source) - [🛠️ Stack Tecnológica](#-stack-tecnológica) - [Backend](#backend) - [Frontend](#frontend) -- [🌟 Mantendo-se à Frente](#-mantendo-se-à-frente) -- [🗺️ Roadmap](#-roadmap) +- [🌟 Mantendo-se à Frente - Cowork Open Source](#-mantendo-se-à-frente---Cowork-open-source) +- [🗺️ Roadmap - Cowork Open Source](#-roadmap---Cowork-open-source) - [🤝 Contribuição](#-contribuição) - [Contribuidores](#contribuidores) - [❤️ Patrocínio](#-patrocínio) @@ -80,7 +80,7 @@ Construído sobre o aclamado projeto open source da [CAMEL-AI][camel-site], noss -## **🚀 Primeiros Passos** +## **🚀 Primeiros Passos com Cowork Open Source** > **🔓 Construído em Público** — Eigent é **100% open source** desde o primeiro dia. Cada funcionalidade, cada commit e cada decisão são transparentes. Acreditamos que as melhores ferramentas de IA devem ser construídas abertamente com a comunidade, e não a portas fechadas. @@ -154,11 +154,11 @@ Para equipes que preferem infraestrutura gerenciada, também oferecemos uma plat Comece em Eigent.ai → -## **✨ Principais recursos** -Desbloqueie todo o potencial de produtividade excepcional com os poderosos recursos do Eigent—construídos para integração perfeita, execução de tarefas mais inteligente e automação ilimitada. +## **✨ Principais recursos - Cowork Open Source** +Desbloqueie todo o potencial de produtividade excepcional com os poderosos recursos do Eigent Cowork código aberto—construídos para integração perfeita, execução de tarefas mais inteligente e automação ilimitada. ### 🏭 Força de Trabalho -Emprega uma equipe de agentes de IA especializados que colaboram para resolver tarefas complexas. O Eigent divide dinamicamente as tarefas e ativa múltiplos agentes para trabalhar **em paralelo.** +Emprega uma equipe de agentes de IA especializados que colaboram para resolver tarefas complexas. O Eigent Cowork código aberto divide dinamicamente as tarefas e ativa múltiplos agentes para trabalhar **em paralelo.** O Eigent pré-definiu os seguintes agentes trabalhadores: @@ -172,7 +172,7 @@ O Eigent pré-definiu os seguintes agentes trabalhadores:
### 🧠 Suporte Abrangente a Modelos -Implante o Eigent localmente com seus modelos preferidos. +Implante o desktop Eigent Cowork código aberto localmente com seus modelos preferidos. ![Model](https://eigent-ai.github.io/.github/assets/gif/feature_local_model.gif) @@ -199,7 +199,9 @@ O Eigent é completamente de código aberto. Você pode baixar, inspecionar e mo
-## 🧩 Casos de Uso +## 🧩 Casos de Uso - Cowork Open Source + +Descubra como desenvolvedores em todo o mundo aproveitam as capacidades de Cowork código aberto do Eigent para automatizar fluxos de trabalho complexos e aumentar a produtividade em diversos setores. ### 1. Itinerário de Viagem de Tênis em Palm Springs com Resumo no Slack [Replay ▶️](https://www.eigent.ai/download?share_token=IjE3NTM0MzUxNTEzMzctNzExMyI.aIeysw.MUeG6ZcBxI1GqvPDvn4dcv-CDWw__1753435151337-7113) @@ -274,6 +276,8 @@ Por favor, adicione esta imagem de assinatura às áreas de assinatura no PDF. V ## 🛠️ Stack Tecnológica +O desktop Eigent Cowork código aberto é construído com tecnologias modernas e confiáveis que garantem escalabilidade, desempenho e extensibilidade. + ### Backend - **Framework:** FastAPI - **Gerenciador de Pacotes:** uv @@ -290,7 +294,7 @@ Por favor, adicione esta imagem de assinatura às áreas de assinatura no PDF. V - **Gerenciamento de Estado:** Zustand - **Editor de Fluxo:** React Flow -## 🌟 Mantendo-se à Frente +## 🌟 Mantendo-se à Frente - Cowork Open Source > \[!IMPORTANT] > @@ -298,7 +302,9 @@ Por favor, adicione esta imagem de assinatura às áreas de assinatura no PDF. V ![][image-star-us] -## 🗺️ Roadmap +## 🗺️ Roadmap - Cowork Open Source + +Nosso Cowork código aberto continua a evoluir com feedback da comunidade. Aqui está o que vem a seguir: | Tópicos | Issues | Canal do Discord | | ------------------------- | -- |-- | diff --git a/backend/app/utils/toolkit/terminal_toolkit.py b/backend/app/utils/toolkit/terminal_toolkit.py index 659decd5..60ff0ecc 100644 --- a/backend/app/utils/toolkit/terminal_toolkit.py +++ b/backend/app/utils/toolkit/terminal_toolkit.py @@ -21,7 +21,7 @@ logger = traceroot.get_logger("terminal_toolkit") # App version - should match electron app version # TODO: Consider getting this from a shared config -APP_VERSION = "0.0.80" +APP_VERSION = "0.0.81" def get_terminal_base_venv_path() -> str: diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 4a54a93a..b9933b20 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -6,7 +6,7 @@ readme = "README.md" requires-python = ">=3.10,<3.11" dependencies = [ "pip>=23.0", - "camel-ai[eigent]==0.2.84", + "camel-ai[eigent]==0.2.85a0", "fastapi>=0.115.12", "fastapi-babel>=1.0.0", "uvicorn[standard]>=0.34.2", diff --git a/backend/uv.lock b/backend/uv.lock index 7a2095e9..7e923d8f 100644 --- a/backend/uv.lock +++ b/backend/uv.lock @@ -261,7 +261,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "aiofiles", specifier = ">=24.1.0" }, - { name = "camel-ai", extras = ["eigent"], specifier = "==0.2.84" }, + { name = "camel-ai", extras = ["eigent"], specifier = "==0.2.85a0" }, { name = "debugpy", specifier = ">=1.8.17" }, { name = "fastapi", specifier = ">=0.115.12" }, { name = "fastapi-babel", specifier = ">=1.0.0" }, @@ -337,7 +337,7 @@ wheels = [ [[package]] name = "camel-ai" -version = "0.2.84" +version = "0.2.85a0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "astor" }, @@ -354,9 +354,9 @@ dependencies = [ { name = "tiktoken" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9b/62/96d922750b304ab2dd0ac1ef35dd3fbbf0e9a44f147e08a1ddfeb94c51c6/camel_ai-0.2.84.tar.gz", hash = "sha256:173c79755fc986e3fa8e27523606222c5f8816fc085abb24831912dcd4a0dec3", size = 1125724, upload-time = "2026-01-20T17:23:13.524Z" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ab/7d305f80e868a60c7097ab510063a171e1798d163b5f8fd7fe7c16553e13/camel_ai-0.2.85a0.tar.gz", hash = "sha256:432de9bac1e40bd4ebf434ca80eaf3993121f87924820e26ad2bad69c1fb5cf5", size = 1126159, upload-time = "2026-01-23T02:24:08.868Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/8b/246abd2c47154de6220fd0a286c3fe50f343d49943ae17e26b9f824a1ca0/camel_ai-0.2.84-py3-none-any.whl", hash = "sha256:63bfbd09e605f9087bb73eb9b929e162fbc6778084ce50e43a367fc0e98cbc65", size = 1599378, upload-time = "2026-01-20T17:23:11.216Z" }, + { url = "https://files.pythonhosted.org/packages/ea/0c/35d73b5d648413844bdfeaf95172a6b7c19802150829f5f907753a773d19/camel_ai-0.2.85a0-py3-none-any.whl", hash = "sha256:6045e9af72fee918ca3acc92f3b4af8af084af7b0cf6435c01a1252bd04ae6b3", size = 1599866, upload-time = "2026-01-23T02:24:06.78Z" }, ] [package.optional-dependencies] diff --git a/electron-builder.json b/electron-builder.json index c2c669cb..2704266f 100644 --- a/electron-builder.json +++ b/electron-builder.json @@ -65,6 +65,26 @@ "hardenedRuntime": true, "gatekeeperAssess": false, "notarize": false, + "signIgnore": [ + ".*\\.py$", + ".*\\.pyc$", + ".*\\.pyo$", + ".*\\.pyi$", + ".*\\.typed$", + ".*\\.txt$", + ".*\\.md$", + ".*\\.rst$", + ".*\\.json$", + ".*\\.yaml$", + ".*\\.yml$", + ".*\\.toml$", + ".*\\.cfg$", + ".*\\.ini$", + ".*\\.csv$", + ".*\\.html$", + ".*\\.css$", + ".*\\.map$" + ], "extendInfo": { "CFBundleURLTypes": [ { diff --git a/electron/main/index.ts b/electron/main/index.ts index 041e8975..8345d6e3 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -36,7 +36,6 @@ import axios from 'axios'; import FormData from 'form-data'; import { checkAndInstallDepsOnUpdate, PromiseReturnType, getInstallationStatus } from './install-deps' import { isBinaryExists, getBackendPath, getVenvPath } from './utils/process' -import { setVibrancy, setRoundedCorners, setTransparentTitlebar } from './native/macos-window' const userData = app.getPath('userData'); @@ -1277,7 +1276,9 @@ async function createWindow() { frame: false, show: false, // Don't show until content is ready to avoid white screen transparent: true, - backgroundColor: '#00000000', + vibrancy: 'sidebar', + visualEffectState: 'active', + backgroundColor: '#f5f5f580', titleBarStyle: isMac ? 'hidden' : undefined, trafficLightPosition: isMac ? { x: 10, y: 10 } : undefined, icon: path.join(VITE_PUBLIC, 'favicon.ico'), @@ -1295,28 +1296,6 @@ async function createWindow() { }, }); - // Apply native macOS effects - if (process.platform === 'darwin') { - win.once('ready-to-show', () => { - if (win && !win.isDestroyed()) { - try { - // Apply vibrancy with HUDWindow material (or others like 'Sidebar', 'UnderWindowBackground') - setVibrancy(win, 'HUDWindow'); - - // Apply rounded corners - setRoundedCorners(win, 20); - - // Make titlebar transparent - setTransparentTitlebar(win); - - log.info('[MacOS] Applied native visual effects'); - } catch (error) { - log.error('[MacOS] Failed to apply native visual effects:', error); - } - } - }); - } - // ==================== Handle renderer crashes and failed loads ==================== win.webContents.on('render-process-gone', (event, details) => { log.error('[RENDERER] Process gone:', details.reason, details.exitCode); diff --git a/electron/main/init.ts b/electron/main/init.ts index 469777a7..bc4f5180 100644 --- a/electron/main/init.ts +++ b/electron/main/init.ts @@ -173,11 +173,6 @@ export async function startBackend(setPort?: (port: number) => void): Promise void): Promise void): Promise { - log.debug(`Backend stdout received ${data.length} bytes`); - displayFilteredLogs(data); - }); - node_process.stderr.on('data', (data) => { - log.debug(`Backend stderr received ${data.length} bytes`); displayFilteredLogs(data); if (data.toString().includes("Address already in use") || diff --git a/electron/main/native/macos-window.ts b/electron/main/native/macos-window.ts deleted file mode 100644 index 7a81e01e..00000000 --- a/electron/main/native/macos-window.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { BrowserWindow } from 'electron'; -import koffi from 'koffi'; -import os from 'os'; - -// NSVisualEffectView material constants (enum values) -export const NSVisualEffectMaterial = { - Titlebar: 3, - Selection: 4, - Menu: 5, - Popover: 6, - Sidebar: 7, - HeaderView: 10, - Sheet: 11, - WindowBackground: 12, - HUDWindow: 13, - FullScreenUI: 15, - ToolTip: 17, - ContentBackground: 18, - UnderWindowBackground: 21, - UnderPageBackground: 22 -} as const; - -export type MaterialType = keyof typeof NSVisualEffectMaterial; - -// Interface for our module functions -interface MacWindowUtils { - setVibrancy: (window: BrowserWindow, material?: MaterialType) => void; - setRoundedCorners: (window: BrowserWindow, radius?: number) => void; - setTransparentTitlebar: (window: BrowserWindow) => void; -} - -let utils: MacWindowUtils; - -if (os.platform() === 'darwin') { - try { - const objc = koffi.load('libobjc.A.dylib'); - - // Types - const Ptr = 'size_t'; - - const objc_getClass = objc.func('objc_getClass', Ptr, ['string']); - const sel_registerName = objc.func('sel_registerName', Ptr, ['string']); - const objc_msgSend = objc.func('objc_msgSend', Ptr, [Ptr, Ptr]); - const objc_msgSend_long = objc.func('objc_msgSend', Ptr, [Ptr, Ptr, 'long']); - const objc_msgSend_double = objc.func('objc_msgSend', Ptr, [Ptr, Ptr, 'double']); - const objc_msgSend_bool = objc.func('objc_msgSend', Ptr, [Ptr, Ptr, 'bool']); - - const NSRect = koffi.struct('NSRect', { - x: 'double', - y: 'double', - width: 'double', - height: 'double' - }); - - const NSVisualEffectBlendingMode = { - BehindWindow: 0, - WithinWindow: 1 - }; - - utils = { - setVibrancy: (window: BrowserWindow, material: MaterialType = 'HUDWindow') => { - try { - const windowHandle = window.getNativeWindowHandle(); - if (windowHandle.length === 0) return; - - // Electron calls valid native handle returns the NSView (BridgedContentView) on macOS - const nsViewPtr = windowHandle.readBigUInt64LE(); - if (!nsViewPtr) return; - - // Selectors - const selAlloc = sel_registerName('alloc'); - const selInit = sel_registerName('init'); - const selSetMaterial = sel_registerName('setMaterial:'); - const selSetBlendingMode = sel_registerName('setBlendingMode:'); - const selSetState = sel_registerName('setState:'); - const selSetAutoresizingMask = sel_registerName('setAutoresizingMask:'); - const selSetFrame = sel_registerName('setFrame:'); - const selAddSubview = sel_registerName('addSubview:positioned:relativeTo:'); - - const NSVisualEffectViewClass = objc_getClass('NSVisualEffectView'); - if (!NSVisualEffectViewClass) return; - - // Allocation - const visualEffectView = objc_msgSend(NSVisualEffectViewClass, selAlloc); - objc_msgSend(visualEffectView, selInit); - - const materialValue = NSVisualEffectMaterial[material] || NSVisualEffectMaterial.HUDWindow; - - // Configuration - objc_msgSend_long(visualEffectView, selSetMaterial, materialValue); - objc_msgSend_long(visualEffectView, selSetBlendingMode, NSVisualEffectBlendingMode.BehindWindow); - objc_msgSend_long(visualEffectView, selSetState, 1); - objc_msgSend_long(visualEffectView, selSetAutoresizingMask, 18); - - // Frame - const bounds = window.getBounds(); - const viewFrame = { x: 0, y: 0, width: bounds.width, height: bounds.height }; - - const objc_msgSend_frame = objc.func('objc_msgSend', 'void', [Ptr, Ptr, NSRect]); - objc_msgSend_frame(visualEffectView, selSetFrame, viewFrame); - - // Add Subview to the CONTENT VIEW (which we already have as nsViewPtr) - const objc_msgSend_positioned = objc.func('objc_msgSend', 'void', [Ptr, Ptr, Ptr, 'long', Ptr]); - objc_msgSend_positioned(nsViewPtr, selAddSubview, visualEffectView, -1, 0); // -1 = NSWindowBelow - - console.log(`[MacOS] Vibrancy applied successfully`); - } catch (error) { - console.error('[MacOS] Error applying vibrancy:', error); - } - }, - - setRoundedCorners: (window: BrowserWindow, radius = 20) => { - try { - const windowHandle = window.getNativeWindowHandle(); - const nsViewPtr = windowHandle.readBigUInt64LE(); - - const selLayer = sel_registerName('layer'); - const selSetWantsLayer = sel_registerName('setWantsLayer:'); - const selSetCornerRadius = sel_registerName('setCornerRadius:'); - const selSetMasksToBounds = sel_registerName('setMasksToBounds:'); - - // Ensure layer-backing - objc_msgSend_bool(nsViewPtr, selSetWantsLayer, true); - - // Get layer - const nsLayer = objc_msgSend(nsViewPtr, selLayer); - if (!nsLayer) return console.error('[MacOS] Failed to get layer'); - - // Apply Corner Radius - objc_msgSend_double(nsLayer, selSetCornerRadius, radius); - objc_msgSend_bool(nsLayer, selSetMasksToBounds, true); - - console.log(`[MacOS] Rounded corners applied: ${radius}`); - } catch (error) { - console.error('[MacOS] Error applying rounded corners:', error); - } - }, - - setTransparentTitlebar: (window: BrowserWindow) => { - try { - const windowHandle = window.getNativeWindowHandle(); - const nsViewPtr = windowHandle.readBigUInt64LE(); - - // We have the View, we need the Window - const selWindow = sel_registerName('window'); - const nsWindowPtr = objc_msgSend(nsViewPtr, selWindow); - - if (!nsWindowPtr) return console.error('[MacOS] Failed to get NSWindow from NSView'); - - const selSetTitlebarAppearsTransparent = sel_registerName('setTitlebarAppearsTransparent:'); - objc_msgSend_bool(nsWindowPtr, selSetTitlebarAppearsTransparent, true); - - console.log('[MacOS] Transparent titlebar applied'); - } catch (error) { - console.error('[MacOS] Error setting transparent titlebar:', error); - } - } - }; - } catch (e) { - console.error('[MacOS] Failed to load native libraries:', e); - utils = { setVibrancy: () => { }, setRoundedCorners: () => { }, setTransparentTitlebar: () => { } }; - } -} else { - utils = { - setVibrancy: () => { }, - setRoundedCorners: () => { }, - setTransparentTitlebar: () => { } - }; -} - -export const { setVibrancy, setRoundedCorners, setTransparentTitlebar } = utils; diff --git a/package.json b/package.json index bf47fee7..5abf6676 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eigent", - "version": "0.0.80", + "version": "0.0.81", "main": "dist-electron/main/index.js", "description": "Eigent", "author": "Eigent.AI", diff --git a/server/pyproject.toml b/server/pyproject.toml index 8a772ab7..b25df2bc 100644 --- a/server/pyproject.toml +++ b/server/pyproject.toml @@ -7,7 +7,7 @@ requires-python = ">=3.12,<3.13" dependencies = [ "alembic>=1.15.2", "openai>=1.99.3,<2", - "camel-ai==0.2.84", + "camel-ai==0.2.85a0", "pydantic[email]>=2.11.1", "click>=8.1.8", "fastapi>=0.115.12", diff --git a/server/uv.lock b/server/uv.lock index 25688bc7..79bae168 100644 --- a/server/uv.lock +++ b/server/uv.lock @@ -145,7 +145,7 @@ wheels = [ [[package]] name = "camel-ai" -version = "0.2.84" +version = "0.2.85a0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "astor" }, @@ -162,9 +162,9 @@ dependencies = [ { name = "tiktoken" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9b/62/96d922750b304ab2dd0ac1ef35dd3fbbf0e9a44f147e08a1ddfeb94c51c6/camel_ai-0.2.84.tar.gz", hash = "sha256:173c79755fc986e3fa8e27523606222c5f8816fc085abb24831912dcd4a0dec3", size = 1125724, upload-time = "2026-01-20T17:23:13.524Z" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ab/7d305f80e868a60c7097ab510063a171e1798d163b5f8fd7fe7c16553e13/camel_ai-0.2.85a0.tar.gz", hash = "sha256:432de9bac1e40bd4ebf434ca80eaf3993121f87924820e26ad2bad69c1fb5cf5", size = 1126159, upload-time = "2026-01-23T02:24:08.868Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/8b/246abd2c47154de6220fd0a286c3fe50f343d49943ae17e26b9f824a1ca0/camel_ai-0.2.84-py3-none-any.whl", hash = "sha256:63bfbd09e605f9087bb73eb9b929e162fbc6778084ce50e43a367fc0e98cbc65", size = 1599378, upload-time = "2026-01-20T17:23:11.216Z" }, + { url = "https://files.pythonhosted.org/packages/ea/0c/35d73b5d648413844bdfeaf95172a6b7c19802150829f5f907753a773d19/camel_ai-0.2.85a0-py3-none-any.whl", hash = "sha256:6045e9af72fee918ca3acc92f3b4af8af084af7b0cf6435c01a1252bd04ae6b3", size = 1599866, upload-time = "2026-01-23T02:24:06.78Z" }, ] [[package]] @@ -364,7 +364,7 @@ requires-dist = [ { name = "alembic", specifier = ">=1.15.2" }, { name = "arrow", specifier = ">=1.3.0" }, { name = "bcrypt", specifier = "==4.0.1" }, - { name = "camel-ai", specifier = "==0.2.84" }, + { name = "camel-ai", specifier = "==0.2.85a0" }, { name = "click", specifier = ">=8.1.8" }, { name = "convert-case", specifier = ">=1.2.3" }, { name = "cryptography", specifier = ">=45.0.4" }, diff --git a/src/components/ChatBox/BottomBox/BoxHeader.tsx b/src/components/ChatBox/BottomBox/BoxHeader.tsx index 79d60860..aa11ced1 100644 --- a/src/components/ChatBox/BottomBox/BoxHeader.tsx +++ b/src/components/ChatBox/BottomBox/BoxHeader.tsx @@ -48,6 +48,7 @@ export interface BoxHeaderConfirmProps { onStartTask?: () => void; onEdit?: () => void; className?: string; + loading?: boolean; } export const BoxHeaderConfirm = ({ @@ -55,6 +56,7 @@ export const BoxHeaderConfirm = ({ onStartTask, onEdit, className, + loading = false, }: BoxHeaderConfirmProps) => { return (
Start Task diff --git a/src/components/ChatBox/BottomBox/index.tsx b/src/components/ChatBox/BottomBox/index.tsx index 2b99dd93..0d0d4998 100644 --- a/src/components/ChatBox/BottomBox/index.tsx +++ b/src/components/ChatBox/BottomBox/index.tsx @@ -93,6 +93,7 @@ export default function BottomBox({ subtitle={subtitle} onStartTask={onStartTask} onEdit={onEdit} + loading={loading} /> )} diff --git a/src/components/Dialog/EndNotice.tsx b/src/components/Dialog/EndNotice.tsx index 1424cd28..e993eec0 100644 --- a/src/components/Dialog/EndNotice.tsx +++ b/src/components/Dialog/EndNotice.tsx @@ -16,9 +16,10 @@ interface Props { onOpenChange: (open: boolean) => void; trigger?: React.ReactNode; onConfirm: () => void; + loading?: boolean; } -export default function EndNoticeDialog({ open, onOpenChange, trigger, onConfirm }: Props) { +export default function EndNoticeDialog({ open, onOpenChange, trigger, onConfirm, loading = false }: Props) { const { t } = useTranslation(); const onSubmit = useCallback(() => { onConfirm(); @@ -36,9 +37,9 @@ export default function EndNoticeDialog({ open, onOpenChange, trigger, onConfirm
- + - + diff --git a/src/components/Folder/ZoomControls.tsx b/src/components/Folder/ZoomControls.tsx new file mode 100644 index 00000000..2fdf8306 --- /dev/null +++ b/src/components/Folder/ZoomControls.tsx @@ -0,0 +1,48 @@ +import { ZoomOut, ZoomIn, RotateCcw } from "lucide-react"; +import { Button } from "../ui/button"; + +// Zoom Controls Component +interface ZoomControlsProps { + zoom: number; + onZoomIn: () => void; + onZoomOut: () => void; + onZoomReset: () => void; +} + +export const ZoomControls = ({ zoom, onZoomIn, onZoomOut, onZoomReset }: ZoomControlsProps) => { + return ( +
+
+ + {zoom}% + +
+ +
+
+ ); +} \ No newline at end of file diff --git a/src/components/Folder/index.tsx b/src/components/Folder/index.tsx index c2f68811..d014116e 100644 --- a/src/components/Folder/index.tsx +++ b/src/components/Folder/index.tsx @@ -9,7 +9,9 @@ import { Folder as FolderIcon, ChevronRight, ChevronDown, + AlertTriangle, } from 'lucide-react'; +import { toast } from 'sonner'; import { Button } from '@/components/ui/button'; import FolderComponent from './FolderComponent'; @@ -19,6 +21,7 @@ import { proxyFetchGet } from '@/api/http'; import { useTranslation } from 'react-i18next'; import useChatStoreAdapter from '@/hooks/useChatStoreAdapter'; import DOMPurify from 'dompurify'; +import { ZoomControls } from './ZoomControls'; // Type definitions interface FileTreeNode { @@ -221,6 +224,16 @@ export default function Folder({ data }: { data?: Agent }) { setIsShowSourceCode(!isShowSourceCode); }; + // State for HTML script approval (lifted from HtmlRenderer) + const [htmlHasScripts, setHtmlHasScripts] = useState(false); + const [htmlScriptsApproved, setHtmlScriptsApproved] = useState(false); + + // Reset script approval when file changes + useEffect(() => { + setHtmlScriptsApproved(false); + setHtmlHasScripts(false); + }, [selectedFile?.path]); + const [isCollapsed, setIsCollapsed] = useState(false); const buildFileTree = (files: FileInfo[]): FileTreeNode => { @@ -235,17 +248,22 @@ export default function Folder({ data }: { data?: Agent }) { nodeMap.set('', root); const sortedFiles = [...files].sort((a, b) => { - const depthA = (a.relativePath || '').split('/').filter(Boolean).length; - const depthB = (b.relativePath || '').split('/').filter(Boolean).length; + // Normalize paths to use forward slashes for cross-platform compatibility + const normalizedPathA = (a.relativePath || '').replace(/\\/g, '/'); + const normalizedPathB = (b.relativePath || '').replace(/\\/g, '/'); + const depthA = normalizedPathA.split('/').filter(Boolean).length; + const depthB = normalizedPathB.split('/').filter(Boolean).length; return depthA - depthB; }); for (const file of sortedFiles) { - const fullRelativePath = file.relativePath - ? `${file.relativePath}/${file.name}` + // Normalize paths to use forward slashes for cross-platform compatibility + const normalizedRelativePath = (file.relativePath || '').replace(/\\/g, '/'); + const fullRelativePath = normalizedRelativePath + ? `${normalizedRelativePath}/${file.name}` : file.name; - const parentPath = file.relativePath || ''; + const parentPath = normalizedRelativePath; const parentNode = nodeMap.get(parentPath) || root; const node: FileTreeNode = { @@ -530,6 +548,28 @@ export default function Folder({ data }: { data?: Agent }) {
+ {/* Safe to Run button for HTML files with scripts */} + {selectedFile?.type === 'html' && !isShowSourceCode && htmlHasScripts && !htmlScriptsApproved && ( + + )} + {selectedFile?.type === 'html' && !isShowSourceCode && htmlScriptsApproved && htmlHasScripts && ( + + + {t('chat.scripts-running')} + + )}