mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-07 10:12:38 +00:00
Compare commits
38 Commits
1.14.4a1
...
devin/1778
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b586968f1 | ||
|
|
d165bcb65f | ||
|
|
fa6287327d | ||
|
|
e961a005cb | ||
|
|
93e786d263 | ||
|
|
ec8a522c2c | ||
|
|
e25f6538a8 | ||
|
|
470d4035db | ||
|
|
57d1b338f7 | ||
|
|
01df19b029 | ||
|
|
dca2c3160f | ||
|
|
6494d68ffc | ||
|
|
f579aa53ae | ||
|
|
a23e118b11 | ||
|
|
095f796922 | ||
|
|
bfbdba426f | ||
|
|
a058a3b15b | ||
|
|
184c228ae9 | ||
|
|
c9100cb51d | ||
|
|
17e82743f6 | ||
|
|
3403f3cba9 | ||
|
|
5db72250b2 | ||
|
|
a071838e92 | ||
|
|
cd2b9ee38a | ||
|
|
07c4a30f2e | ||
|
|
b30fdbaa0e | ||
|
|
898f860916 | ||
|
|
2c0323c3fe | ||
|
|
c580d428f0 | ||
|
|
70f391994e | ||
|
|
864f0a8a91 | ||
|
|
9f13235037 | ||
|
|
c7f01048b7 | ||
|
|
14c3963d2c | ||
|
|
feb2e715a3 | ||
|
|
e0b86750c2 | ||
|
|
2a40316521 | ||
|
|
e2deac5575 |
5
.github/security.md
vendored
5
.github/security.md
vendored
@@ -5,7 +5,10 @@ CrewAI ecosystem.
|
||||
|
||||
### How to Report
|
||||
|
||||
Please submit reports to **crewai-vdp-ess@submit.bugcrowd.com**
|
||||
Please submit reports through one of the following channels:
|
||||
|
||||
- **crewai-vdp-ess@submit.bugcrowd.com**
|
||||
- https://security.crewai.com
|
||||
|
||||
- **Please do not** disclose vulnerabilities via public GitHub issues, pull requests,
|
||||
or social media
|
||||
|
||||
@@ -19,7 +19,7 @@ repos:
|
||||
language: system
|
||||
pass_filenames: true
|
||||
types: [python]
|
||||
exclude: ^(lib/crewai/src/crewai/cli/templates/|lib/crewai/tests/|lib/crewai-tools/tests/|lib/crewai-files/tests/)
|
||||
exclude: ^(lib/crewai/src/crewai/cli/templates/|lib/cli/src/crewai_cli/templates/|lib/cli/tests/|lib/crewai/tests/|lib/crewai-tools/tests/|lib/crewai-files/tests/|lib/devtools/tests/)
|
||||
- repo: https://github.com/astral-sh/uv-pre-commit
|
||||
rev: 0.11.3
|
||||
hooks:
|
||||
|
||||
@@ -54,12 +54,13 @@ _original_from_serialized_response = getattr(
|
||||
)
|
||||
|
||||
if _original_from_serialized_response is not None:
|
||||
_from_serialized: Any = _original_from_serialized_response
|
||||
|
||||
def _patched_from_serialized_response(
|
||||
request: Any, serialized_response: Any, history: Any = None
|
||||
) -> Any:
|
||||
"""Patched version that ensures response._content is properly set."""
|
||||
response = _original_from_serialized_response(request, serialized_response, history)
|
||||
response = _from_serialized(request, serialized_response, history)
|
||||
# Explicitly set _content to avoid ResponseNotRead errors
|
||||
# The content was passed to the constructor but the mocked read() prevents
|
||||
# proper initialization of the internal state
|
||||
@@ -255,7 +256,8 @@ def vcr_cassette_dir(request: Any) -> str:
|
||||
|
||||
for parent in test_file.parents:
|
||||
if (
|
||||
parent.name in ("crewai", "crewai-tools", "crewai-files")
|
||||
parent.name
|
||||
in ("crewai", "crewai-tools", "crewai-files", "cli", "crewai-core")
|
||||
and parent.parent.name == "lib"
|
||||
):
|
||||
package_root = parent
|
||||
|
||||
@@ -26,7 +26,7 @@ mode: "wide"
|
||||
</Step>
|
||||
|
||||
<Step title="مراقبة التقدم">
|
||||
استخدم `GET /{kickoff_id}/status` للتحقق من حالة التنفيذ واسترجاع النتائج.
|
||||
استخدم `GET /status/{kickoff_id}` للتحقق من حالة التنفيذ واسترجاع النتائج.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
@@ -65,7 +65,7 @@ https://your-crew-name.crewai.com
|
||||
|
||||
1. **الاكتشاف**: استدعِ `GET /inputs` لفهم ما يحتاجه طاقمك
|
||||
2. **التنفيذ**: أرسل المدخلات عبر `POST /kickoff` لبدء المعالجة
|
||||
3. **المراقبة**: استعلم عن `GET /{kickoff_id}/status` حتى الاكتمال
|
||||
3. **المراقبة**: استعلم عن `GET /status/{kickoff_id}` حتى الاكتمال
|
||||
4. **النتائج**: استخرج المخرجات النهائية من الاستجابة المكتملة
|
||||
|
||||
## معالجة الأخطاء
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "GET /{kickoff_id}/status"
|
||||
title: "GET /status/{kickoff_id}"
|
||||
description: "الحصول على حالة التنفيذ"
|
||||
openapi: "/enterprise-api.en.yaml GET /{kickoff_id}/status"
|
||||
openapi: "/enterprise-api.en.yaml GET /status/{kickoff_id}"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
@@ -4,6 +4,122 @@ description: "تحديثات المنتج والتحسينات وإصلاحات
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="7 مايو 2026">
|
||||
## v1.14.5a3
|
||||
|
||||
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a3)
|
||||
|
||||
## ما الذي تغير
|
||||
|
||||
### إصلاحات الأخطاء
|
||||
- إصلاح مسار نقطة النهاية للحالة من /{kickoff_id}/status إلى /status/{kickoff_id}
|
||||
- تحديث تبعية gitpython إلى الإصدار >=3.1.47 للامتثال الأمني
|
||||
|
||||
### إعادة هيكلة
|
||||
- استخراج واجهة سطر الأوامر إلى حزمة crewai-cli المستقلة
|
||||
|
||||
### الوثائق
|
||||
- تحديث سجل التغييرات والإصدار للإصدار v1.14.5a2
|
||||
|
||||
## المساهمون
|
||||
|
||||
@greysonlalonde, @iris-clawd
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="4 مايو 2026">
|
||||
## v1.14.5a2
|
||||
|
||||
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a2)
|
||||
|
||||
## ما الذي تغير
|
||||
|
||||
### إصلاحات الأخطاء
|
||||
- إصلاح استعادة مخرجات المهام في كتلة finally
|
||||
- تضمين `thoughts_token_count` في رموز الإكمال
|
||||
- الحفاظ على مخرجات المهام عبر تفريغ دفعات غير متزامنة
|
||||
- تمرير kwargs إلى استدعاءات المحمل في `CrewAIRagAdapter`
|
||||
- منع `result_as_answer` من إرجاع رسالة كتلة الخطاف كإجابة نهائية
|
||||
- منع `result_as_answer` من إرجاع خطأ كإجابة نهائية
|
||||
- استخدام `acall` لتحويل المخرجات في المسارات غير المتزامنة
|
||||
- منع تغيير كلمات التوقف المشتركة في LLM عبر الوكلاء
|
||||
- التعامل مع مدخلات `BaseModel` في `convert_to_model`
|
||||
|
||||
### الوثائق
|
||||
- توثيق متغيرات البيئة الإضافية
|
||||
- تحديث سجل التغييرات والإصدار لـ v1.14.5a1
|
||||
|
||||
## المساهمون
|
||||
|
||||
@NIK-TIGER-BILL, @greysonlalonde, @lorenzejay, @minasami-pr, @theCyberTech, @wishhyt
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="1 مايو 2026">
|
||||
## v1.14.5a1
|
||||
|
||||
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a1)
|
||||
|
||||
## ما الذي تغير
|
||||
|
||||
### الميزات
|
||||
- إضافة معلمة بدء `restore_from_state_id`
|
||||
- إضافة تسليط الضوء على ExaSearchTool وإعادة تسميته من EXASearchTool
|
||||
|
||||
### إصلاحات الأخطاء
|
||||
- إصلاح المواقع المفقودة لـ crewai في تدفق الإصدار
|
||||
- ضمان تحميل أحداث المهارات للآثار
|
||||
|
||||
### الوثائق
|
||||
- تحديث سجل التغييرات والإصدار لـ v1.14.4
|
||||
|
||||
## المساهمون
|
||||
|
||||
@akaKuruma, @github-actions[bot], @greysonlalonde, @lorenzejay, @theishangoswami
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="1 مايو 2026">
|
||||
## v1.14.4
|
||||
|
||||
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.4)
|
||||
|
||||
## ما الذي تغير
|
||||
|
||||
### الميزات
|
||||
- إضافة دعم لمفتاح الاستمرارية المخصص في @persist
|
||||
- إضافة دعم واجهة برمجة التطبيقات للردود لمزود Azure OpenAI
|
||||
- تمرير credential_scopes إلى عميل Azure AI Inference
|
||||
- إضافة دليل إعداد هوية عبء العمل لـ Vertex AI
|
||||
- إضافة Tavily Research والحصول على Research
|
||||
- إضافة أدوات MCP من You.com للبحث، البحث، واستخراج المحتوى
|
||||
|
||||
### إصلاحات الأخطاء
|
||||
- إصلاح مشكلة السقوط عند عدم تطابق تعبير JSON regex مع JSON صالح
|
||||
- إصلاح للحفاظ على tool_calls عندما تحتوي الاستجابة أيضًا على نص
|
||||
- إصلاح لتمرير base_url و api_key إلى instructor.from_provider
|
||||
- إصلاح لتحذير وإرجاع فارغ عندما لا يُرجع خادم MCP الأصلي أي أدوات
|
||||
- إصلاح لاستخدام متغير الرسائل الموثقة في معالجات غير البث
|
||||
- إصلاح لحماية مساعدي وصف دردشة الطاقم ضد فشل LLM
|
||||
- إصلاح لإعادة تعيين الرسائل والتكرارات بين الاستدعاءات
|
||||
- إصلاح لتمرير ملف trained-agents من خلال replay و test
|
||||
- إصلاح لاحترام ملف trained-agents المخصص في الاستدلال
|
||||
- إصلاح لربط الوكلاء المخصصين بالمهام فقط بالطاقم لملفات الإدخال متعددة الأنماط
|
||||
- إصلاح لتسلسل callable الحواجز كـ null لتسجيل JSON
|
||||
- إصلاح إعادة تسمية force_final_answer لتجنب توجيه ذاتي
|
||||
- إصلاح زيادة litellm لإصلاح SSTI؛ تجاهل CVE غير القابل للإصلاح في pip
|
||||
|
||||
### الوثائق
|
||||
- تحديث سجل التغييرات والإصدار لـ v1.14.4a1
|
||||
- إضافة صفحة أدوات E2B Sandbox
|
||||
- إضافة وثائق أدوات صندوق Daytona
|
||||
|
||||
## المساهمون
|
||||
|
||||
@EdwardIrby, @dependabot[bot], @factory-droid-oss, @factory-droid[bot], @greysonlalonde, @kunalk16, @lorenzejay, @lucasgomide, @manisrinivasan2k1, @mattatcha, @vinibrsl
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="29 أبريل 2026">
|
||||
## v1.14.4a1
|
||||
|
||||
|
||||
@@ -380,6 +380,42 @@ class AnotherFlow(Flow[dict]):
|
||||
print("Method-level persisted runs:", self.state["runs"])
|
||||
```
|
||||
|
||||
### تفرع الحالة المستمرة
|
||||
|
||||
يدعم `@persist` نمطين متميزين للترطيب في `kickoff` / `kickoff_async`:
|
||||
|
||||
- `kickoff(inputs={"id": <uuid>})` — **استئناف**: يحمّل أحدث لقطة لـ UUID المقدم ويستمر في الكتابة تحت نفس `flow_uuid`. يمتد التاريخ.
|
||||
- `kickoff(restore_from_state_id=<uuid>)` — **تفرع**: يحمّل أحدث لقطة لـ UUID المقدم، يرطّب حالة التشغيل الجديد منها، ثم يعيّن `state.id` جديدًا (مولّدًا تلقائيًا، أو `inputs["id"]` إذا تم تثبيته). تذهب كتابات `@persist` للتشغيل الجديد تحت `state.id` الجديد؛ يتم الحفاظ على تاريخ تدفق المصدر.
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai.flow.persistence import persist
|
||||
from pydantic import BaseModel
|
||||
|
||||
class CounterState(BaseModel):
|
||||
id: str = ""
|
||||
counter: int = 0
|
||||
|
||||
@persist
|
||||
class CounterFlow(Flow[CounterState]):
|
||||
@start()
|
||||
def step(self):
|
||||
self.state.counter += 1
|
||||
print(f"[id={self.state.id}] counter={self.state.counter}")
|
||||
|
||||
# التشغيل 1: حالة جديدة، العداد 0 -> 1، محفوظ تحت flow_1.state.id
|
||||
flow_1 = CounterFlow()
|
||||
flow_1.kickoff()
|
||||
|
||||
# التفرع: ترطيب من أحدث لقطة لـ flow_1، لكن باستخدام state.id جديد
|
||||
flow_2 = CounterFlow()
|
||||
flow_2.kickoff(restore_from_state_id=flow_1.state.id)
|
||||
# يبدأ flow_2.state.counter بـ 1 (مرطّب)، ثم تزيده step() إلى 2.
|
||||
# flow_2.state.id != flow_1.state.id؛ تاريخ flow_1 لم يتغيّر.
|
||||
```
|
||||
|
||||
إذا لم يطابق `restore_from_state_id` المقدم أي حالة مستمرة، يعود kickoff بصمت إلى السلوك الافتراضي — نفس سلوك `inputs["id"]` عند عدم العثور عليه. الجمع بين `restore_from_state_id` و `from_checkpoint` يطلق `ValueError`؛ اختر مصدر ترطيب واحدًا. تثبيت `inputs["id"]` أثناء التفرع يشارك مفتاح الاستمرارية مع تدفق آخر — عادةً ما تريد استخدام `restore_from_state_id` فقط.
|
||||
|
||||
### كيف تعمل
|
||||
|
||||
1. **تعريف الحالة الفريد**
|
||||
|
||||
@@ -146,6 +146,14 @@ class ProductionFlow(Flow[AppState]):
|
||||
# ...
|
||||
```
|
||||
|
||||
افتراضيًا، يستأنف `@persist` تدفقًا عند توفير `kickoff(inputs={"id": <uuid>})`، مما يمدّ نفس تاريخ `flow_uuid`. لـ **تفرع** تدفق مستمر إلى نسبٍ جديد — ترطيب الحالة من تشغيل سابق ولكن الكتابة تحت `state.id` جديد — مرّر `restore_from_state_id`:
|
||||
|
||||
```python
|
||||
flow.kickoff(restore_from_state_id="<previous-run-state-id>")
|
||||
```
|
||||
|
||||
يحصل التشغيل الجديد على `state.id` جديد (مولّد تلقائيًا، أو `inputs["id"]` إذا تم تثبيته) لذا لا تمتد كتابات `@persist` الخاصة به إلى تاريخ المصدر. الجمع مع `from_checkpoint` يطلق `ValueError`؛ اختر مصدر ترطيب واحدًا.
|
||||
|
||||
## الخلاصة
|
||||
|
||||
- **ابدأ بتدفق.**
|
||||
|
||||
@@ -133,7 +133,7 @@ crew.kickoff()
|
||||
| **DirectorySearchTool** | أداة RAG للبحث في المجلدات، مفيدة للتنقل في أنظمة الملفات. |
|
||||
| **DOCXSearchTool** | أداة RAG للبحث في مستندات DOCX، مثالية لمعالجة ملفات Word. |
|
||||
| **DirectoryReadTool** | تسهّل قراءة ومعالجة هياكل المجلدات ومحتوياتها. |
|
||||
| **EXASearchTool** | أداة مصممة لإجراء عمليات بحث شاملة عبر مصادر بيانات متنوعة. |
|
||||
| **ExaSearchTool** | أداة مصممة لإجراء عمليات بحث شاملة عبر مصادر بيانات متنوعة. |
|
||||
| **FileReadTool** | تُمكّن قراءة واستخراج البيانات من الملفات، مع دعم تنسيقات ملفات متنوعة. |
|
||||
| **FirecrawlSearchTool** | أداة للبحث في صفحات الويب باستخدام Firecrawl وإرجاع النتائج. |
|
||||
| **FirecrawlCrawlWebsiteTool** | أداة لزحف صفحات الويب باستخدام Firecrawl. |
|
||||
|
||||
@@ -116,6 +116,48 @@ class PersistentCounterFlow(Flow[CounterState]):
|
||||
return self.state.value
|
||||
```
|
||||
|
||||
#### تفرع الحالة المستمرة
|
||||
|
||||
يدعم `@persist` نمطين متميزين للترطيب في `kickoff` / `kickoff_async`. استخدم **استئناف** (`inputs["id"]`) لمواصلة نفس النسب؛ استخدم **تفرع** (`restore_from_state_id`) لبدء نسبٍ جديد من لقطة:
|
||||
|
||||
| | `state.id` بعد kickoff | كتابات `@persist` تذهب إلى |
|
||||
|---|---|---|
|
||||
| `inputs["id"]` (استئناف) | المعرّف المقدم | المعرّف المقدم (يمد التاريخ) |
|
||||
| `restore_from_state_id` (تفرع) | معرّف جديد، أو `inputs["id"]` إذا ثُبّت | المعرّف الجديد (المصدر محفوظ) |
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai.flow.persistence import persist
|
||||
from pydantic import BaseModel
|
||||
|
||||
class CounterState(BaseModel):
|
||||
id: str = ""
|
||||
counter: int = 0
|
||||
|
||||
@persist
|
||||
class CounterFlow(Flow[CounterState]):
|
||||
@start()
|
||||
def step(self):
|
||||
self.state.counter += 1
|
||||
|
||||
# التشغيل 1: حالة جديدة، العداد 0 -> 1
|
||||
flow_1 = CounterFlow()
|
||||
flow_1.kickoff()
|
||||
|
||||
# التفرع: الترطيب من أحدث لقطة لـ flow_1، لكن الكتابة تحت state.id جديد
|
||||
flow_2 = CounterFlow()
|
||||
flow_2.kickoff(restore_from_state_id=flow_1.state.id)
|
||||
# يبدأ flow_2 بـ counter=1 (مرطّب)، ثم تزيده step() إلى 2.
|
||||
# تاريخ flow_uuid لـ flow_1 لم يتغيّر.
|
||||
```
|
||||
|
||||
ملاحظات السلوك:
|
||||
|
||||
- `restore_from_state_id` غير موجود في الاستمرارية → يعود kickoff بصمت إلى السلوك الافتراضي (يعكس سلوك `inputs["id"]` عند عدم العثور عليه). لا يُطلق أي استثناء.
|
||||
- الجمع بين `restore_from_state_id` و `from_checkpoint` يطلق `ValueError` — يستهدفان نظامي حالة مختلفين (`@persist` مقابل Checkpointing) ولا يمكن الجمع بينهما.
|
||||
- `restore_from_state_id=None` (افتراضي) متطابق بايت ببايت مع kickoff بدون المعامل.
|
||||
- تثبيت `inputs["id"]` أثناء التفرع يعني أن التشغيل الجديد يشارك مفتاح الاستمرارية مع تدفق آخر — عادةً ما تريد فقط `restore_from_state_id`.
|
||||
|
||||
## أنماط حالة متقدمة
|
||||
|
||||
### المنطق الشرطي المبني على الحالة
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "أداة بحث Exa"
|
||||
description: "ابحث في الويب باستخدام Exa Search API للعثور على النتائج الأكثر صلة لأي استعلام، مع خيارات لمحتوى الصفحة الكامل والمقتطفات والملخصات."
|
||||
description: "ابحث في الويب باستخدام Exa Search API للعثور على النتائج الأكثر صلة لأي استعلام، مع خيارات لمحتوى الصفحة الكامل والمقتطفات."
|
||||
icon: "magnifying-glass"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
تتيح أداة `EXASearchTool` لوكلاء CrewAI البحث في الويب باستخدام [Exa](https://exa.ai/) search API. تُرجع النتائج الأكثر صلة لأي استعلام، مع خيارات لمحتوى الصفحة الكامل والملخصات المولّدة بالذكاء الاصطناعي.
|
||||
تتيح أداة `ExaSearchTool` لوكلاء CrewAI البحث في الويب باستخدام [Exa](https://exa.ai/) search API. تُرجع النتائج الأكثر صلة لأي استعلام، مع خيارات لمحتوى الصفحة الكامل والمقتطفات الموفرة للرموز.
|
||||
|
||||
## التثبيت
|
||||
|
||||
@@ -27,15 +27,15 @@ export EXA_API_KEY='your_exa_api_key'
|
||||
|
||||
## مثال على الاستخدام
|
||||
|
||||
إليك كيفية استخدام `EXASearchTool` مع وكيل CrewAI:
|
||||
إليك كيفية استخدام `ExaSearchTool` مع وكيل CrewAI:
|
||||
|
||||
```python
|
||||
import os
|
||||
from crewai import Agent, Task, Crew
|
||||
from crewai_tools import EXASearchTool
|
||||
from crewai_tools import ExaSearchTool
|
||||
|
||||
# Initialize the tool
|
||||
exa_tool = EXASearchTool()
|
||||
exa_tool = ExaSearchTool()
|
||||
|
||||
# Create an agent that uses the tool
|
||||
researcher = Agent(
|
||||
@@ -66,11 +66,11 @@ print(result)
|
||||
|
||||
## خيارات التكوين
|
||||
|
||||
تقبل أداة `EXASearchTool` المعاملات التالية أثناء التهيئة:
|
||||
تقبل أداة `ExaSearchTool` المعاملات التالية أثناء التهيئة:
|
||||
|
||||
- `type` (str، اختياري): نوع البحث المستخدم. الافتراضي هو `"auto"`. الخيارات: `"auto"`، `"instant"`، `"fast"`، `"deep"`.
|
||||
- `highlights` (bool أو dict، اختياري): إرجاع مقتطفات موفرة للرموز أكثر صلة بالاستعلام بدلاً من الصفحة الكاملة. الافتراضي هو `True`. مرر قاموسًا مثل `{"max_characters": 4000}` للتكوين، أو `False` للتعطيل.
|
||||
- `content` (bool، اختياري): ما إذا كان يجب تضمين محتوى الصفحة الكامل في النتائج. الافتراضي هو `False`.
|
||||
- `summary` (bool، اختياري): ما إذا كان يجب تضمين ملخصات مولّدة بالذكاء الاصطناعي لكل نتيجة. يتطلب `content=True`. الافتراضي هو `False`.
|
||||
- `api_key` (str، اختياري): مفتاح Exa API الخاص بك. يعود إلى متغير البيئة `EXA_API_KEY` إذا لم يتم تقديمه.
|
||||
- `base_url` (str، اختياري): عنوان URL مخصص لخادم API. يعود إلى متغير البيئة `EXA_BASE_URL` إذا لم يتم تقديمه.
|
||||
|
||||
@@ -86,25 +86,52 @@ print(result)
|
||||
يمكنك تكوين الأداة بمعاملات مخصصة للحصول على نتائج أغنى:
|
||||
|
||||
```python
|
||||
# Get full page content with AI summaries
|
||||
exa_tool = EXASearchTool(
|
||||
content=True,
|
||||
summary=True,
|
||||
# Use 'deep' for thorough, multi-step searches
|
||||
exa_tool = ExaSearchTool(
|
||||
highlights=True,
|
||||
type="deep"
|
||||
)
|
||||
|
||||
# Use it in an agent
|
||||
agent = Agent(
|
||||
role="Deep Researcher",
|
||||
goal="Conduct thorough research with full content and summaries",
|
||||
goal="Conduct thorough research",
|
||||
tools=[exa_tool]
|
||||
)
|
||||
```
|
||||
|
||||
## استخدام Exa عبر MCP
|
||||
|
||||
يمكنك أيضًا ربط وكيلك بخادم MCP المستضاف من Exa. مرّر مفتاح API الخاص بك عبر ترويسة `x-api-key`:
|
||||
|
||||
```python
|
||||
from crewai import Agent
|
||||
from crewai.mcp import MCPServerHTTP
|
||||
|
||||
agent = Agent(
|
||||
role="Research Analyst",
|
||||
goal="Find and analyze information on the web",
|
||||
backstory="Expert researcher with access to Exa's tools",
|
||||
mcps=[
|
||||
MCPServerHTTP(
|
||||
url="https://mcp.exa.ai/mcp",
|
||||
headers={"x-api-key": "YOUR_EXA_API_KEY"},
|
||||
),
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
احصل على مفتاح API من [لوحة تحكم Exa](https://dashboard.exa.ai/api-keys). لمزيد من المعلومات حول MCP في CrewAI، راجع [نظرة عامة على MCP](/ar/mcp/overview).
|
||||
|
||||
## الميزات
|
||||
|
||||
- **مقتطفات موفرة للرموز**: الحصول على المقتطفات الأكثر صلة من كل نتيجة، باستخدام رموز أقل بكثير من النص الكامل
|
||||
- **البحث الدلالي**: العثور على نتائج بناءً على المعنى، وليس الكلمات المفتاحية فقط
|
||||
- **استرجاع المحتوى الكامل**: الحصول على النص الكامل لصفحات الويب مع نتائج البحث
|
||||
- **ملخصات الذكاء الاصطناعي**: الحصول على ملخصات موجزة مولّدة بالذكاء الاصطناعي لكل نتيجة
|
||||
- **تصفية التاريخ**: تقييد النتائج لفترات زمنية محددة باستخدام فلاتر تاريخ النشر
|
||||
- **تصفية النطاقات**: تقييد عمليات البحث على نطاقات محددة
|
||||
- **تصفية النطاقات**: تقييد عمليات البحث على نطاقات محددة
|
||||
|
||||
## موارد
|
||||
|
||||
- [توثيق Exa](https://exa.ai/docs)
|
||||
- [لوحة تحكم Exa — إدارة مفاتيح API والاستخدام](https://dashboard.exa.ai)
|
||||
1893
docs/docs.json
1893
docs/docs.json
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@ Welcome to the CrewAI AMP API reference. This API allows you to programmatically
|
||||
</Step>
|
||||
|
||||
<Step title="Monitor Progress">
|
||||
Use `GET /{kickoff_id}/status` to check execution status and retrieve results.
|
||||
Use `GET /status/{kickoff_id}` to check execution status and retrieve results.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
@@ -65,7 +65,7 @@ Replace `your-crew-name` with your actual crew's URL from the dashboard.
|
||||
|
||||
1. **Discovery**: Call `GET /inputs` to understand what your crew needs
|
||||
2. **Execution**: Submit inputs via `POST /kickoff` to start processing
|
||||
3. **Monitoring**: Poll `GET /{kickoff_id}/status` until completion
|
||||
3. **Monitoring**: Poll `GET /status/{kickoff_id}` until completion
|
||||
4. **Results**: Extract the final output from the completed response
|
||||
|
||||
## Error Handling
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "GET /{kickoff_id}/status"
|
||||
title: "GET /status/{kickoff_id}"
|
||||
description: "Get execution status"
|
||||
openapi: "/enterprise-api.en.yaml GET /{kickoff_id}/status"
|
||||
openapi: "/enterprise-api.en.yaml GET /status/{kickoff_id}"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
@@ -4,6 +4,122 @@ description: "Product updates, improvements, and bug fixes for CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="May 07, 2026">
|
||||
## v1.14.5a3
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a3)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Bug Fixes
|
||||
- Fix status endpoint path from /{kickoff_id}/status to /status/{kickoff_id}
|
||||
- Bump gitpython dependency to version >=3.1.47 for security compliance
|
||||
|
||||
### Refactoring
|
||||
- Extract CLI into standalone crewai-cli package
|
||||
|
||||
### Documentation
|
||||
- Update changelog and version for v1.14.5a2
|
||||
|
||||
## Contributors
|
||||
|
||||
@greysonlalonde, @iris-clawd
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="May 04, 2026">
|
||||
## v1.14.5a2
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a2)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Bug Fixes
|
||||
- Fix task output restoration in finally block
|
||||
- Include `thoughts_token_count` in completion tokens
|
||||
- Preserve task outputs across async batch flush
|
||||
- Forward kwargs to loader calls in `CrewAIRagAdapter`
|
||||
- Prevent `result_as_answer` from returning hook-block message as final answer
|
||||
- Prevent `result_as_answer` from returning error as final answer
|
||||
- Use `acall` for output conversion in async paths
|
||||
- Prevent shared LLM stop words mutation across agents
|
||||
- Handle `BaseModel` input in `convert_to_model`
|
||||
|
||||
### Documentation
|
||||
- Document additional environment variables
|
||||
- Update changelog and version for v1.14.5a1
|
||||
|
||||
## Contributors
|
||||
|
||||
@NIK-TIGER-BILL, @greysonlalonde, @lorenzejay, @minasami-pr, @theCyberTech, @wishhyt
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="May 01, 2026">
|
||||
## v1.14.5a1
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a1)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Add `restore_from_state_id` kickoff parameter
|
||||
- Add highlights to ExaSearchTool and rename from EXASearchTool
|
||||
|
||||
### Bug Fixes
|
||||
- Fix missing crewai pin sites in release flow
|
||||
- Ensure skills loading events for traces
|
||||
|
||||
### Documentation
|
||||
- Update changelog and version for v1.14.4
|
||||
|
||||
## Contributors
|
||||
|
||||
@akaKuruma, @github-actions[bot], @greysonlalonde, @lorenzejay, @theishangoswami
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="May 01, 2026">
|
||||
## v1.14.4
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.4)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Add support for custom persistence key in @persist
|
||||
- Add Responses API support for Azure OpenAI provider
|
||||
- Forward credential_scopes to Azure AI Inference client
|
||||
- Add Vertex AI workload identity setup guide
|
||||
- Add Tavily Research and get Research
|
||||
- Add You.com MCP tools for search, research, and content extraction
|
||||
|
||||
### Bug Fixes
|
||||
- Fix fall through when JSON regex match isn't valid JSON
|
||||
- Fix to preserve tool_calls when response also contains text
|
||||
- Fix to forward base_url and api_key to instructor.from_provider
|
||||
- Fix to warn and return empty when native MCP server returns no tools
|
||||
- Fix to use validated messages variable in non-streaming handlers
|
||||
- Fix to guard crew chat description helpers against LLM failures
|
||||
- Fix to reset messages and iterations between invocations
|
||||
- Fix to forward trained-agents file through replay and test
|
||||
- Fix to honor custom trained-agents file at inference
|
||||
- Fix to bind task-only agents to crew for multimodal input_files
|
||||
- Fix to serialize guardrail callables as null for JSON checkpointing
|
||||
- Fix renaming of force_final_answer to avoid self-referential router
|
||||
- Fix bump of litellm for SSTI fix; ignore unfixable pip CVE
|
||||
|
||||
### Documentation
|
||||
- Update changelog and version for v1.14.4a1
|
||||
- Add E2B Sandbox Tools page
|
||||
- Add Daytona sandbox tools documentation
|
||||
|
||||
## Contributors
|
||||
|
||||
@EdwardIrby, @dependabot[bot], @factory-droid-oss, @factory-droid[bot], @greysonlalonde, @kunalk16, @lorenzejay, @lucasgomide, @manisrinivasan2k1, @mattatcha, @vinibrsl
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Apr 29, 2026">
|
||||
## v1.14.4a1
|
||||
|
||||
|
||||
@@ -380,6 +380,42 @@ class AnotherFlow(Flow[dict]):
|
||||
print("Method-level persisted runs:", self.state["runs"])
|
||||
```
|
||||
|
||||
### Forking Persisted State
|
||||
|
||||
`@persist` supports two distinct hydration modes on `kickoff` / `kickoff_async`:
|
||||
|
||||
- `kickoff(inputs={"id": <uuid>})` — **resume**: load the latest snapshot for the supplied UUID and continue writing under the same `flow_uuid`. The history extends.
|
||||
- `kickoff(restore_from_state_id=<uuid>)` — **fork**: load the latest snapshot for the supplied UUID, hydrate the new run's state from it, and assign a fresh `state.id` (auto-generated, or `inputs["id"]` if pinned). The new run's `@persist` writes land under the new `state.id`; the source flow's history is preserved.
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai.flow.persistence import persist
|
||||
from pydantic import BaseModel
|
||||
|
||||
class CounterState(BaseModel):
|
||||
id: str = ""
|
||||
counter: int = 0
|
||||
|
||||
@persist
|
||||
class CounterFlow(Flow[CounterState]):
|
||||
@start()
|
||||
def step(self):
|
||||
self.state.counter += 1
|
||||
print(f"[id={self.state.id}] counter={self.state.counter}")
|
||||
|
||||
# Run 1: fresh state, counter 0 -> 1, persisted under flow_1.state.id
|
||||
flow_1 = CounterFlow()
|
||||
flow_1.kickoff()
|
||||
|
||||
# Fork: hydrate from flow_1's latest snapshot, but use a NEW state.id
|
||||
flow_2 = CounterFlow()
|
||||
flow_2.kickoff(restore_from_state_id=flow_1.state.id)
|
||||
# flow_2.state.counter starts at 1 (hydrated), then step() bumps it to 2.
|
||||
# flow_2.state.id != flow_1.state.id; flow_1's history is unchanged.
|
||||
```
|
||||
|
||||
If the supplied `restore_from_state_id` does not match any persisted state, the kickoff falls back silently — same as the existing `inputs["id"]` resume not-found behavior. Combining `restore_from_state_id` with `from_checkpoint` raises a `ValueError`; pick one hydration source. Pinning `inputs["id"]` while forking shares a persistence key with another flow — usually you want only `restore_from_state_id`.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Unique State Identification**
|
||||
|
||||
@@ -146,6 +146,14 @@ class ProductionFlow(Flow[AppState]):
|
||||
# ...
|
||||
```
|
||||
|
||||
By default, `@persist` resumes a flow when `kickoff(inputs={"id": <uuid>})` is supplied, extending the same `flow_uuid` history. To **fork** a persisted flow into a new lineage — hydrate state from a previous run but write under a fresh `state.id` — pass `restore_from_state_id`:
|
||||
|
||||
```python
|
||||
flow.kickoff(restore_from_state_id="<previous-run-state-id>")
|
||||
```
|
||||
|
||||
The new run gets a fresh `state.id` (auto-generated, or `inputs["id"]` if pinned) so its `@persist` writes don't extend the source's history. Combining with `from_checkpoint` raises a `ValueError`; pick one hydration source.
|
||||
|
||||
## Summary
|
||||
|
||||
- **Start with a Flow.**
|
||||
|
||||
@@ -133,7 +133,7 @@ Here is a list of the available tools and their descriptions:
|
||||
| **DirectorySearchTool** | A RAG tool for searching within directories, useful for navigating through file systems. |
|
||||
| **DOCXSearchTool** | A RAG tool aimed at searching within DOCX documents, ideal for processing Word files. |
|
||||
| **DirectoryReadTool** | Facilitates reading and processing of directory structures and their contents. |
|
||||
| **EXASearchTool** | A tool designed for performing exhaustive searches across various data sources. |
|
||||
| **ExaSearchTool** | Search the web with Exa, the fastest and most accurate web search API. Supports token-efficient highlights and full page content. |
|
||||
| **FileReadTool** | Enables reading and extracting data from files, supporting various file formats. |
|
||||
| **FirecrawlSearchTool** | A tool to search webpages using Firecrawl and return the results. |
|
||||
| **FirecrawlCrawlWebsiteTool** | A tool for crawling webpages using Firecrawl. |
|
||||
|
||||
@@ -346,6 +346,48 @@ class SelectivePersistFlow(Flow):
|
||||
return f"Complete with count {self.state['count']}"
|
||||
```
|
||||
|
||||
#### Forking Persisted State
|
||||
|
||||
`@persist` supports two distinct hydration modes on `kickoff` / `kickoff_async`. Use **resume** (`inputs["id"]`) to continue the same lineage; use **fork** (`restore_from_state_id`) to start a new lineage seeded from a snapshot:
|
||||
|
||||
| | `state.id` after kickoff | `@persist` writes land under |
|
||||
|---|---|---|
|
||||
| `inputs["id"]` (resume) | supplied id | supplied id (extends history) |
|
||||
| `restore_from_state_id` (fork) | fresh id, or `inputs["id"]` if pinned | new id (source preserved) |
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai.flow.persistence import persist
|
||||
from pydantic import BaseModel
|
||||
|
||||
class CounterState(BaseModel):
|
||||
id: str = ""
|
||||
counter: int = 0
|
||||
|
||||
@persist
|
||||
class CounterFlow(Flow[CounterState]):
|
||||
@start()
|
||||
def step(self):
|
||||
self.state.counter += 1
|
||||
|
||||
# Run 1: fresh state, counter 0 -> 1
|
||||
flow_1 = CounterFlow()
|
||||
flow_1.kickoff()
|
||||
|
||||
# Fork: hydrate from flow_1's latest snapshot, but write under a NEW state.id
|
||||
flow_2 = CounterFlow()
|
||||
flow_2.kickoff(restore_from_state_id=flow_1.state.id)
|
||||
# flow_2 starts with counter=1 (hydrated), then step() bumps it to 2.
|
||||
# flow_1's flow_uuid history is unchanged.
|
||||
```
|
||||
|
||||
Behavior notes:
|
||||
|
||||
- `restore_from_state_id` not found in persistence → the kickoff falls back silently to default behavior (mirrors the existing `inputs["id"]` resume not-found behavior). No exception is raised.
|
||||
- Combining `restore_from_state_id` with `from_checkpoint` raises a `ValueError` — they target different state systems (`@persist` vs. Checkpointing) and cannot be combined.
|
||||
- `restore_from_state_id=None` (default) is byte-identical to a kickoff without the parameter.
|
||||
- Pinning `inputs["id"]` while forking means the new run shares a persistence key with another flow — usually you want only `restore_from_state_id`.
|
||||
|
||||
|
||||
## Advanced State Patterns
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "Exa Search Tool"
|
||||
description: "Search the web using the Exa Search API to find the most relevant results for any query, with options for full page content, highlights, and summaries."
|
||||
description: "Search the web with Exa, the fastest and most accurate web search API. Get token-efficient highlights and full page content."
|
||||
icon: "magnifying-glass"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
The `EXASearchTool` lets CrewAI agents search the web using the [Exa](https://exa.ai/) search API. It returns the most relevant results for any query, with options for full page content and AI-generated summaries.
|
||||
The `ExaSearchTool` lets CrewAI agents search the web using [Exa](https://exa.ai/), the fastest and most accurate web search API. It returns the most relevant results for any query, with options for token-efficient highlights and full page content.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -27,15 +27,15 @@ Get an API key from the [Exa dashboard](https://dashboard.exa.ai/api-keys).
|
||||
|
||||
## Example Usage
|
||||
|
||||
Here's how to use the `EXASearchTool` within a CrewAI agent:
|
||||
Here's how to use the `ExaSearchTool` within a CrewAI agent:
|
||||
|
||||
```python
|
||||
import os
|
||||
from crewai import Agent, Task, Crew
|
||||
from crewai_tools import EXASearchTool
|
||||
from crewai_tools import ExaSearchTool
|
||||
|
||||
# Initialize the tool
|
||||
exa_tool = EXASearchTool()
|
||||
exa_tool = ExaSearchTool()
|
||||
|
||||
# Create an agent that uses the tool
|
||||
researcher = Agent(
|
||||
@@ -66,11 +66,11 @@ print(result)
|
||||
|
||||
## Configuration Options
|
||||
|
||||
The `EXASearchTool` accepts the following parameters during initialization:
|
||||
The `ExaSearchTool` accepts the following parameters during initialization:
|
||||
|
||||
- `type` (str, optional): The search type to use. Defaults to `"auto"`. Options: `"auto"`, `"instant"`, `"fast"`, `"deep"`.
|
||||
- `highlights` (bool or dict, optional): Return token-efficient excerpts most relevant to the query instead of the full page. Defaults to `True`. Pass a dict like `{"max_characters": 4000}` to configure, or `False` to disable.
|
||||
- `content` (bool, optional): Whether to include full page content in results. Defaults to `False`.
|
||||
- `summary` (bool, optional): Whether to include AI-generated summaries of each result. Requires `content=True`. Defaults to `False`.
|
||||
- `api_key` (str, optional): Your Exa API key. Falls back to the `EXA_API_KEY` environment variable if not provided.
|
||||
- `base_url` (str, optional): Custom API server URL. Falls back to the `EXA_BASE_URL` environment variable if not provided.
|
||||
|
||||
@@ -83,28 +83,70 @@ When calling the tool (or when an agent invokes it), the following search parame
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
You can configure the tool with custom parameters for richer results:
|
||||
For most agent workflows we recommend `highlights` — it returns the most relevant excerpts from each result and uses far fewer tokens than full page content:
|
||||
|
||||
```python
|
||||
# Get full page content with AI summaries
|
||||
exa_tool = EXASearchTool(
|
||||
content=True,
|
||||
summary=True,
|
||||
type="deep"
|
||||
# Get token-efficient excerpts most relevant to the query
|
||||
exa_tool = ExaSearchTool(
|
||||
highlights=True,
|
||||
type="auto",
|
||||
)
|
||||
|
||||
# Use it in an agent
|
||||
agent = Agent(
|
||||
role="Deep Researcher",
|
||||
goal="Conduct thorough research with full content and summaries",
|
||||
role="Researcher",
|
||||
goal="Answer questions with current web data",
|
||||
tools=[exa_tool]
|
||||
)
|
||||
```
|
||||
|
||||
For thorough, multi-step searches, use `type="deep"`:
|
||||
|
||||
```python
|
||||
exa_tool = ExaSearchTool(
|
||||
highlights=True,
|
||||
type="deep",
|
||||
)
|
||||
```
|
||||
|
||||
For more on choosing between highlights and full content, see the [Exa search best practices](https://exa.ai/docs/reference/search-best-practices).
|
||||
|
||||
## Using Exa via MCP
|
||||
|
||||
You can also connect your agent to Exa's hosted MCP server. Pass your API key with the `x-api-key` header:
|
||||
|
||||
```python
|
||||
from crewai import Agent
|
||||
from crewai.mcp import MCPServerHTTP
|
||||
|
||||
agent = Agent(
|
||||
role="Research Analyst",
|
||||
goal="Find and analyze information on the web",
|
||||
backstory="Expert researcher with access to Exa's tools",
|
||||
mcps=[
|
||||
MCPServerHTTP(
|
||||
url="https://mcp.exa.ai/mcp",
|
||||
headers={"x-api-key": "YOUR_EXA_API_KEY"},
|
||||
),
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
Get your API key from the [Exa dashboard](https://dashboard.exa.ai/api-keys). For more on MCP in CrewAI, see the [MCP overview](/en/mcp/overview).
|
||||
|
||||
## Features
|
||||
|
||||
- **Token-Efficient Highlights**: Get the most relevant excerpts from each result, ~10x fewer tokens than full text
|
||||
- **Semantic Search**: Find results based on meaning, not just keywords
|
||||
- **Full Content Retrieval**: Get the full text of web pages alongside search results
|
||||
- **AI Summaries**: Get concise, AI-generated summaries of each result
|
||||
- **Date Filtering**: Limit results to specific time periods with published date filters
|
||||
- **Domain Filtering**: Restrict searches to specific domains
|
||||
|
||||
<Note>
|
||||
`EXASearchTool` is a deprecated alias for `ExaSearchTool`. Existing imports continue to work but will emit a deprecation warning; please migrate to `ExaSearchTool`.
|
||||
</Note>
|
||||
|
||||
## Resources
|
||||
|
||||
- [Exa documentation](https://exa.ai/docs)
|
||||
- [Exa dashboard — manage API keys and usage](https://dashboard.exa.ai)
|
||||
|
||||
@@ -35,7 +35,7 @@ info:
|
||||
|
||||
1. **Discover inputs** using `GET /inputs`
|
||||
2. **Start execution** using `POST /kickoff`
|
||||
3. **Monitor progress** using `GET /{kickoff_id}/status`
|
||||
3. **Monitor progress** using `GET /status/{kickoff_id}`
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: CrewAI Support
|
||||
@@ -207,7 +207,7 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/ServerError"
|
||||
|
||||
/{kickoff_id}/status:
|
||||
/status/{kickoff_id}:
|
||||
get:
|
||||
summary: Get Execution Status
|
||||
description: |
|
||||
|
||||
@@ -35,7 +35,7 @@ info:
|
||||
|
||||
1. **Discover inputs** using `GET /inputs`
|
||||
2. **Start execution** using `POST /kickoff`
|
||||
3. **Monitor progress** using `GET /{kickoff_id}/status`
|
||||
3. **Monitor progress** using `GET /status/{kickoff_id}`
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: CrewAI Support
|
||||
@@ -207,7 +207,7 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/ServerError"
|
||||
|
||||
/{kickoff_id}/status:
|
||||
/status/{kickoff_id}:
|
||||
get:
|
||||
summary: Get Execution Status
|
||||
description: |
|
||||
|
||||
@@ -84,7 +84,7 @@ paths:
|
||||
'500':
|
||||
$ref: '#/components/responses/ServerError'
|
||||
|
||||
/{kickoff_id}/status:
|
||||
/status/{kickoff_id}:
|
||||
get:
|
||||
summary: 실행 상태 조회
|
||||
description: |
|
||||
|
||||
@@ -35,7 +35,7 @@ info:
|
||||
|
||||
1. **Descubra os inputs** usando `GET /inputs`
|
||||
2. **Inicie a execução** usando `POST /kickoff`
|
||||
3. **Monitore o progresso** usando `GET /{kickoff_id}/status`
|
||||
3. **Monitore o progresso** usando `GET /status/{kickoff_id}`
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: CrewAI Suporte
|
||||
@@ -120,7 +120,7 @@ paths:
|
||||
"500":
|
||||
$ref: "#/components/responses/ServerError"
|
||||
|
||||
/{kickoff_id}/status:
|
||||
/status/{kickoff_id}:
|
||||
get:
|
||||
summary: Obter Status da Execução
|
||||
description: |
|
||||
|
||||
@@ -26,7 +26,7 @@ CrewAI 엔터프라이즈 API 참고 자료에 오신 것을 환영합니다.
|
||||
</Step>
|
||||
|
||||
<Step title="진행 상황 모니터링">
|
||||
`GET /{kickoff_id}/status`를 사용하여 실행 상태를 확인하고 결과를 조회하세요.
|
||||
`GET /status/{kickoff_id}`를 사용하여 실행 상태를 확인하고 결과를 조회하세요.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
@@ -65,7 +65,7 @@ https://your-crew-name.crewai.com
|
||||
|
||||
1. **탐색**: `GET /inputs`를 호출하여 crew가 필요한 것을 파악합니다.
|
||||
2. **실행**: `POST /kickoff`를 통해 입력값을 제출하여 처리를 시작합니다.
|
||||
3. **모니터링**: 완료될 때까지 `GET /{kickoff_id}/status`를 주기적으로 조회합니다.
|
||||
3. **모니터링**: 완료될 때까지 `GET /status/{kickoff_id}`를 주기적으로 조회합니다.
|
||||
4. **결과**: 완료된 응답에서 최종 출력을 추출합니다.
|
||||
|
||||
## 오류 처리
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "GET /{kickoff_id}/status"
|
||||
title: "GET /status/{kickoff_id}"
|
||||
description: "실행 상태 조회"
|
||||
openapi: "/enterprise-api.ko.yaml GET /{kickoff_id}/status"
|
||||
openapi: "/enterprise-api.ko.yaml GET /status/{kickoff_id}"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
@@ -4,6 +4,122 @@ description: "CrewAI의 제품 업데이트, 개선 사항 및 버그 수정"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="2026년 5월 7일">
|
||||
## v1.14.5a3
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a3)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 버그 수정
|
||||
- 상태 엔드포인트 경로를 /{kickoff_id}/status에서 /status/{kickoff_id}로 수정
|
||||
- 보안 준수를 위해 gitpython 의존성을 버전 >=3.1.47로 업데이트
|
||||
|
||||
### 리팩토링
|
||||
- CLI를 독립형 crewai-cli 패키지로 분리
|
||||
|
||||
### 문서
|
||||
- v1.14.5a2에 대한 변경 로그 및 버전 업데이트
|
||||
|
||||
## 기여자
|
||||
|
||||
@greysonlalonde, @iris-clawd
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 5월 4일">
|
||||
## v1.14.5a2
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a2)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 버그 수정
|
||||
- finally 블록에서 작업 출력 복원 수정
|
||||
- 완료 토큰에 `thoughts_token_count` 포함
|
||||
- 비동기 배치 플러시 간 작업 출력 보존
|
||||
- `CrewAIRagAdapter`의 로더 호출에 kwargs 전달
|
||||
- `result_as_answer`가 후크 차단 메시지를 최종 답변으로 반환하지 않도록 방지
|
||||
- `result_as_answer`가 오류를 최종 답변으로 반환하지 않도록 방지
|
||||
- 비동기 경로에서 출력 변환을 위해 `acall` 사용
|
||||
- 에이전트 간 공유 LLM 중지 단어 변형 방지
|
||||
- `convert_to_model`에서 `BaseModel` 입력 처리
|
||||
|
||||
### 문서화
|
||||
- 추가 환경 변수 문서화
|
||||
- v1.14.5a1에 대한 변경 로그 및 버전 업데이트
|
||||
|
||||
## 기여자
|
||||
|
||||
@NIK-TIGER-BILL, @greysonlalonde, @lorenzejay, @minasami-pr, @theCyberTech, @wishhyt
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 5월 1일">
|
||||
## v1.14.5a1
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a1)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- `restore_from_state_id` 시작 매개변수 추가
|
||||
- ExaSearchTool에 하이라이트 추가 및 EXASearchTool에서 이름 변경
|
||||
|
||||
### 버그 수정
|
||||
- 릴리스 흐름에서 crewai 핀 사이트 누락 수정
|
||||
- 트레이스를 위한 기술 로딩 이벤트 보장
|
||||
|
||||
### 문서
|
||||
- v1.14.4에 대한 변경 로그 및 버전 업데이트
|
||||
|
||||
## 기여자
|
||||
|
||||
@akaKuruma, @github-actions[bot], @greysonlalonde, @lorenzejay, @theishangoswami
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 5월 1일">
|
||||
## v1.14.4
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.14.4)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- @persist에서 사용자 정의 지속성 키 지원 추가
|
||||
- Azure OpenAI 공급자를 위한 응답 API 지원 추가
|
||||
- Azure AI 추론 클라이언트에 credential_scopes 전달
|
||||
- Vertex AI 작업 부하 신원 설정 가이드 추가
|
||||
- Tavily Research 및 Research 가져오기 추가
|
||||
- 검색, 연구 및 콘텐츠 추출을 위한 You.com MCP 도구 추가
|
||||
|
||||
### 버그 수정
|
||||
- JSON 정규 표현식이 유효한 JSON이 아닐 때의 fall through 수정
|
||||
- 응답에 텍스트가 포함될 때 tool_calls를 보존하도록 수정
|
||||
- instructor.from_provider에 base_url 및 api_key를 전달하도록 수정
|
||||
- 기본 MCP 서버가 도구를 반환하지 않을 때 경고하고 빈 값을 반환하도록 수정
|
||||
- 비스트리밍 핸들러에서 검증된 메시지 변수를 사용하도록 수정
|
||||
- LLM 실패에 대한 크루 채팅 설명 도우미를 보호하도록 수정
|
||||
- 호출 간 메시지 및 반복을 재설정하도록 수정
|
||||
- replay 및 test를 통해 훈련된 에이전트 파일을 전달하도록 수정
|
||||
- 추론 시 사용자 정의 훈련된 에이전트 파일을 존중하도록 수정
|
||||
- 다중 모드 input_files에 대해 작업 전용 에이전트를 크루에 바인딩하도록 수정
|
||||
- JSON 체크포인팅을 위해 가드레일 호출 가능 항목을 null로 직렬화하도록 수정
|
||||
- 자기 참조 라우터를 피하기 위해 force_final_answer의 이름 변경 수정
|
||||
- SSTI 수정을 위한 litellm 버전 증가; 수정할 수 없는 pip CVE 무시
|
||||
|
||||
### 문서
|
||||
- v1.14.4a1에 대한 변경 로그 및 버전 업데이트
|
||||
- E2B 샌드박스 도구 페이지 추가
|
||||
- Daytona 샌드박스 도구 문서 추가
|
||||
|
||||
## 기여자
|
||||
|
||||
@EdwardIrby, @dependabot[bot], @factory-droid-oss, @factory-droid[bot], @greysonlalonde, @kunalk16, @lorenzejay, @lucasgomide, @manisrinivasan2k1, @mattatcha, @vinibrsl
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 4월 29일">
|
||||
## v1.14.4a1
|
||||
|
||||
|
||||
@@ -373,6 +373,42 @@ class AnotherFlow(Flow[dict]):
|
||||
print("Method-level persisted runs:", self.state["runs"])
|
||||
```
|
||||
|
||||
### 영속 상태 포크하기
|
||||
|
||||
`@persist`는 `kickoff` / `kickoff_async`에서 두 가지 별개의 하이드레이션 모드를 지원합니다:
|
||||
|
||||
- `kickoff(inputs={"id": <uuid>})` — **재개(resume)**: 제공된 UUID에 대한 최신 스냅샷을 로드하고 동일한 `flow_uuid` 아래에서 계속 기록합니다. 기록이 확장됩니다.
|
||||
- `kickoff(restore_from_state_id=<uuid>)` — **포크(fork)**: 제공된 UUID에 대한 최신 스냅샷을 로드하고 새 실행의 상태를 하이드레이트한 후, 새로운 `state.id`(자동 생성, 또는 `inputs["id"]`가 고정된 경우 그 값)를 할당합니다. 새 실행의 `@persist` 기록은 새로운 `state.id` 아래에 저장되며, 원본 플로우의 기록은 보존됩니다.
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai.flow.persistence import persist
|
||||
from pydantic import BaseModel
|
||||
|
||||
class CounterState(BaseModel):
|
||||
id: str = ""
|
||||
counter: int = 0
|
||||
|
||||
@persist
|
||||
class CounterFlow(Flow[CounterState]):
|
||||
@start()
|
||||
def step(self):
|
||||
self.state.counter += 1
|
||||
print(f"[id={self.state.id}] counter={self.state.counter}")
|
||||
|
||||
# 실행 1: 새 상태, counter 0 -> 1, flow_1.state.id 아래에 저장됨
|
||||
flow_1 = CounterFlow()
|
||||
flow_1.kickoff()
|
||||
|
||||
# 포크: flow_1의 최신 스냅샷에서 하이드레이트하지만, 새 state.id를 사용
|
||||
flow_2 = CounterFlow()
|
||||
flow_2.kickoff(restore_from_state_id=flow_1.state.id)
|
||||
# flow_2.state.counter는 1(하이드레이트)로 시작하고, step()이 2로 증가시킵니다.
|
||||
# flow_2.state.id != flow_1.state.id; flow_1의 기록은 변경되지 않습니다.
|
||||
```
|
||||
|
||||
제공된 `restore_from_state_id`가 어떤 영속 상태와도 일치하지 않으면, kickoff는 조용히 기본 동작으로 폴백됩니다 — 기존 `inputs["id"]`의 미발견 동작과 동일합니다. `restore_from_state_id`를 `from_checkpoint`와 결합하면 `ValueError`가 발생합니다; 하나의 하이드레이션 소스를 선택하세요. 포크 중 `inputs["id"]`를 고정하면 다른 플로우와 영속 키를 공유하게 됩니다 — 일반적으로 `restore_from_state_id`만 사용하는 것이 좋습니다.
|
||||
|
||||
### 작동 방식
|
||||
|
||||
1. **고유 상태 식별**
|
||||
|
||||
@@ -146,6 +146,14 @@ class ProductionFlow(Flow[AppState]):
|
||||
# ...
|
||||
```
|
||||
|
||||
기본적으로, `@persist`는 `kickoff(inputs={"id": <uuid>})`가 제공될 때 플로우를 재개하여 동일한 `flow_uuid` 기록을 확장합니다. 영속된 플로우를 새 계보로 **포크**하려면 — 이전 실행에서 상태를 하이드레이트하지만 새로운 `state.id` 아래에 기록 — `restore_from_state_id`를 전달하세요:
|
||||
|
||||
```python
|
||||
flow.kickoff(restore_from_state_id="<previous-run-state-id>")
|
||||
```
|
||||
|
||||
새 실행은 새로운 `state.id`(자동 생성, 또는 `inputs["id"]`가 고정된 경우 그 값)를 받아 `@persist` 기록이 원본의 기록을 확장하지 않도록 합니다. `from_checkpoint`와 결합하면 `ValueError`가 발생합니다; 하나의 하이드레이션 소스를 선택하세요.
|
||||
|
||||
## 요약
|
||||
|
||||
- **Flow로 시작하세요.**
|
||||
|
||||
@@ -132,7 +132,7 @@ crew.kickoff()
|
||||
| **DirectorySearchTool** | 디렉터리 내에서 검색하는 RAG 도구로, 파일 시스템을 탐색할 때 유용합니다. |
|
||||
| **DOCXSearchTool** | DOCX 문서 내에서 검색하는 데 특화된 RAG 도구로, Word 파일을 처리할 때 이상적입니다. |
|
||||
| **DirectoryReadTool** | 디렉터리 구조와 그 내용을 읽고 처리하도록 지원하는 도구입니다. |
|
||||
| **EXASearchTool** | 다양한 데이터 소스를 폭넓게 검색하기 위해 설계된 도구입니다. |
|
||||
| **ExaSearchTool** | 다양한 데이터 소스를 폭넓게 검색하기 위해 설계된 도구입니다. |
|
||||
| **FileReadTool** | 다양한 파일 형식을 지원하며 파일에서 데이터를 읽고 추출할 수 있는 도구입니다. |
|
||||
| **FirecrawlSearchTool** | Firecrawl을 이용해 웹페이지를 검색하고 결과를 반환하는 도구입니다. |
|
||||
| **FirecrawlCrawlWebsiteTool** | Firecrawl을 사용해 웹페이지를 크롤링하는 도구입니다. |
|
||||
|
||||
@@ -346,6 +346,48 @@ class SelectivePersistFlow(Flow):
|
||||
return f"Complete with count {self.state['count']}"
|
||||
```
|
||||
|
||||
#### 영속 상태 포크하기
|
||||
|
||||
`@persist`는 `kickoff` / `kickoff_async`에서 두 가지 별개의 하이드레이션 모드를 지원합니다. 동일한 계보를 계속하려면 **재개**(`inputs["id"]`)를 사용하고, 스냅샷에서 시작하는 새 계보를 시작하려면 **포크**(`restore_from_state_id`)를 사용하세요:
|
||||
|
||||
| | kickoff 후 `state.id` | `@persist` 기록 위치 |
|
||||
|---|---|---|
|
||||
| `inputs["id"]` (재개) | 제공된 id | 제공된 id (기록 확장) |
|
||||
| `restore_from_state_id` (포크) | 새 id, 또는 고정 시 `inputs["id"]` | 새 id (원본 보존) |
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai.flow.persistence import persist
|
||||
from pydantic import BaseModel
|
||||
|
||||
class CounterState(BaseModel):
|
||||
id: str = ""
|
||||
counter: int = 0
|
||||
|
||||
@persist
|
||||
class CounterFlow(Flow[CounterState]):
|
||||
@start()
|
||||
def step(self):
|
||||
self.state.counter += 1
|
||||
|
||||
# 실행 1: 새 상태, counter 0 -> 1
|
||||
flow_1 = CounterFlow()
|
||||
flow_1.kickoff()
|
||||
|
||||
# 포크: flow_1의 최신 스냅샷에서 하이드레이트, 단 새 state.id에 기록
|
||||
flow_2 = CounterFlow()
|
||||
flow_2.kickoff(restore_from_state_id=flow_1.state.id)
|
||||
# flow_2는 counter=1(하이드레이트)로 시작하고, step()이 2로 증가시킵니다.
|
||||
# flow_1의 flow_uuid 기록은 변경되지 않습니다.
|
||||
```
|
||||
|
||||
동작 노트:
|
||||
|
||||
- `restore_from_state_id`가 영속에서 발견되지 않음 → kickoff는 조용히 기본 동작으로 폴백됩니다 (기존 `inputs["id"]`의 미발견 동작 미러링). 예외는 발생하지 않습니다.
|
||||
- `restore_from_state_id`를 `from_checkpoint`와 결합하면 `ValueError`가 발생합니다 — 서로 다른 상태 시스템(`@persist` 대 Checkpointing)을 대상으로 하므로 결합할 수 없습니다.
|
||||
- `restore_from_state_id=None`(기본값)은 매개변수 없는 kickoff와 바이트 단위로 동일합니다.
|
||||
- 포크 중 `inputs["id"]`를 고정하면 새 실행이 다른 플로우와 영속 키를 공유함을 의미합니다 — 일반적으로 `restore_from_state_id`만 사용하는 것이 좋습니다.
|
||||
|
||||
## 고급 상태 패턴
|
||||
|
||||
### 상태 기반 조건부 로직
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
---
|
||||
title: EXA 검색 웹 로더
|
||||
description: EXASearchTool은 인터넷 전반에 걸쳐 텍스트의 내용에서 지정된 쿼리에 대한 시맨틱 검색을 수행하도록 설계되었습니다.
|
||||
description: ExaSearchTool은 인터넷 전반에 걸쳐 텍스트의 내용에서 지정된 쿼리에 대한 시맨틱 검색을 수행하도록 설계되었습니다.
|
||||
icon: globe-pointer
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
# `EXASearchTool`
|
||||
# `ExaSearchTool`
|
||||
|
||||
## 설명
|
||||
|
||||
EXASearchTool은 텍스트의 내용을 기반으로 지정된 쿼리를 인터넷 전반에 걸쳐 의미론적으로 검색하도록 설계되었습니다.
|
||||
ExaSearchTool은 텍스트의 내용을 기반으로 지정된 쿼리를 인터넷 전반에 걸쳐 의미론적으로 검색하도록 설계되었습니다.
|
||||
사용자가 제공한 쿼리를 기반으로 가장 관련성 높은 검색 결과를 가져오고 표시하기 위해 [exa.ai](https://exa.ai/) API를 활용합니다.
|
||||
|
||||
## 설치
|
||||
@@ -25,15 +25,15 @@ pip install 'crewai[tools]'
|
||||
다음 예제는 도구를 초기화하고 주어진 쿼리로 검색을 실행하는 방법을 보여줍니다:
|
||||
|
||||
```python Code
|
||||
from crewai_tools import EXASearchTool
|
||||
from crewai_tools import ExaSearchTool
|
||||
|
||||
# Initialize the tool for internet searching capabilities
|
||||
tool = EXASearchTool()
|
||||
tool = ExaSearchTool()
|
||||
```
|
||||
|
||||
## 시작 단계
|
||||
|
||||
EXASearchTool을 효과적으로 사용하려면 다음 단계를 따르세요:
|
||||
ExaSearchTool을 효과적으로 사용하려면 다음 단계를 따르세요:
|
||||
|
||||
<Steps>
|
||||
<Step title="패키지 설치">
|
||||
@@ -47,7 +47,35 @@ EXASearchTool을 효과적으로 사용하려면 다음 단계를 따르세요:
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## MCP를 통한 Exa 사용
|
||||
|
||||
Exa가 호스팅하는 MCP 서버에 에이전트를 연결할 수도 있습니다. API 키는 `x-api-key` 헤더로 전달하세요:
|
||||
|
||||
```python
|
||||
from crewai import Agent
|
||||
from crewai.mcp import MCPServerHTTP
|
||||
|
||||
agent = Agent(
|
||||
role="Research Analyst",
|
||||
goal="Find and analyze information on the web",
|
||||
backstory="Expert researcher with access to Exa's tools",
|
||||
mcps=[
|
||||
MCPServerHTTP(
|
||||
url="https://mcp.exa.ai/mcp",
|
||||
headers={"x-api-key": "YOUR_EXA_API_KEY"},
|
||||
),
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
API 키는 [Exa 대시보드](https://dashboard.exa.ai/api-keys)에서 발급받을 수 있습니다. CrewAI에서의 MCP 사용에 대한 자세한 내용은 [MCP 개요](/ko/mcp/overview)를 참고하세요.
|
||||
|
||||
## 결론
|
||||
|
||||
`EXASearchTool`을 Python 프로젝트에 통합함으로써, 사용자는 애플리케이션 내에서 실시간으로 인터넷을 직접 검색할 수 있는 능력을 얻게 됩니다.
|
||||
`ExaSearchTool`을 Python 프로젝트에 통합함으로써, 사용자는 애플리케이션 내에서 실시간으로 인터넷을 직접 검색할 수 있는 능력을 얻게 됩니다.
|
||||
제공된 설정 및 사용 지침을 따르면, 이 도구를 프로젝트에 포함하는 과정이 간편하고 직관적입니다.
|
||||
|
||||
## 참고 자료
|
||||
|
||||
- [Exa 공식 문서](https://exa.ai/docs)
|
||||
- [Exa 대시보드 — API 키 및 사용량 관리](https://dashboard.exa.ai)
|
||||
|
||||
@@ -26,7 +26,7 @@ Bem-vindo à referência da API do CrewAI AMP. Esta API permite que você intera
|
||||
</Step>
|
||||
|
||||
<Step title="Monitore o Progresso">
|
||||
Use `GET /{kickoff_id}/status` para checar o status da execução e recuperar os resultados.
|
||||
Use `GET /status/{kickoff_id}` para checar o status da execução e recuperar os resultados.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
@@ -65,7 +65,7 @@ Substitua `your-crew-name` pela URL real do seu crew no painel.
|
||||
|
||||
1. **Descoberta**: Chame `GET /inputs` para entender o que seu crew precisa
|
||||
2. **Execução**: Envie os inputs via `POST /kickoff` para iniciar o processamento
|
||||
3. **Monitoramento**: Faça polling em `GET /{kickoff_id}/status` até a conclusão
|
||||
3. **Monitoramento**: Faça polling em `GET /status/{kickoff_id}` até a conclusão
|
||||
4. **Resultados**: Extraia o output final da resposta concluída
|
||||
|
||||
## Tratamento de Erros
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "GET /{kickoff_id}/status"
|
||||
title: "GET /status/{kickoff_id}"
|
||||
description: "Obter o status da execução"
|
||||
openapi: "/enterprise-api.pt-BR.yaml GET /{kickoff_id}/status"
|
||||
openapi: "/enterprise-api.pt-BR.yaml GET /status/{kickoff_id}"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
@@ -4,6 +4,122 @@ description: "Atualizações de produto, melhorias e correções do CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="07 mai 2026">
|
||||
## v1.14.5a3
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a3)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Correções de Bugs
|
||||
- Corrigir o caminho do endpoint de status de /{kickoff_id}/status para /status/{kickoff_id}
|
||||
- Atualizar a dependência gitpython para a versão >=3.1.47 para conformidade de segurança
|
||||
|
||||
### Refatoração
|
||||
- Extrair CLI para o pacote independente crewai-cli
|
||||
|
||||
### Documentação
|
||||
- Atualizar o changelog e a versão para v1.14.5a2
|
||||
|
||||
## Contributors
|
||||
|
||||
@greysonlalonde, @iris-clawd
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="04 mai 2026">
|
||||
## v1.14.5a2
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a2)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Correções de Bugs
|
||||
- Corrigir a restauração da saída da tarefa no bloco finally
|
||||
- Incluir `thoughts_token_count` nos tokens de conclusão
|
||||
- Preservar as saídas das tarefas durante o descarregamento assíncrono em lote
|
||||
- Encaminhar kwargs para chamadas de carregador em `CrewAIRagAdapter`
|
||||
- Impedir que `result_as_answer` retorne mensagem de bloqueio de hook como resposta final
|
||||
- Impedir que `result_as_answer` retorne erro como resposta final
|
||||
- Usar `acall` para conversão de saída em caminhos assíncronos
|
||||
- Prevenir a mutação de palavras de parada compartilhadas do LLM entre agentes
|
||||
- Lidar com entrada `BaseModel` em `convert_to_model`
|
||||
|
||||
### Documentação
|
||||
- Documentar variáveis de ambiente adicionais
|
||||
- Atualizar changelog e versão para v1.14.5a1
|
||||
|
||||
## Contribuidores
|
||||
|
||||
@NIK-TIGER-BILL, @greysonlalonde, @lorenzejay, @minasami-pr, @theCyberTech, @wishhyt
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="01 mai 2026">
|
||||
## v1.14.5a1
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a1)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Recursos
|
||||
- Adicionar parâmetro de início `restore_from_state_id`
|
||||
- Adicionar destaques ao ExaSearchTool e renomear de EXASearchTool
|
||||
|
||||
### Correções de Bugs
|
||||
- Corrigir sites de pinos do crewai ausentes no fluxo de lançamento
|
||||
- Garantir eventos de carregamento de habilidades para rastros
|
||||
|
||||
### Documentação
|
||||
- Atualizar changelog e versão para v1.14.4
|
||||
|
||||
## Contribuidores
|
||||
|
||||
@akaKuruma, @github-actions[bot], @greysonlalonde, @lorenzejay, @theishangoswami
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="01 mai 2026">
|
||||
## v1.14.4
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.4)
|
||||
|
||||
## O que mudou
|
||||
|
||||
### Recursos
|
||||
- Adicionar suporte para chave de persistência personalizada em @persist
|
||||
- Adicionar suporte à API de Respostas para o provedor Azure OpenAI
|
||||
- Encaminhar credential_scopes para o cliente de Inferência da Azure AI
|
||||
- Adicionar guia de configuração de identidade de carga de trabalho do Vertex AI
|
||||
- Adicionar Tavily Research e obter Pesquisa
|
||||
- Adicionar ferramentas MCP do You.com para pesquisa, pesquisa e extração de conteúdo
|
||||
|
||||
### Correções de Bugs
|
||||
- Corrigir falha quando a correspondência de regex JSON não é um JSON válido
|
||||
- Corrigir para preservar tool_calls quando a resposta também contém texto
|
||||
- Corrigir para encaminhar base_url e api_key para instructor.from_provider
|
||||
- Corrigir para avisar e retornar vazio quando o servidor MCP nativo não retorna ferramentas
|
||||
- Corrigir para usar a variável de mensagens validadas em manipuladores não-streaming
|
||||
- Corrigir para proteger os ajudantes de descrição do chat da equipe contra falhas do LLM
|
||||
- Corrigir para redefinir mensagens e iterações entre invocações
|
||||
- Corrigir para encaminhar o arquivo de agentes treinados através de replay e teste
|
||||
- Corrigir para honrar o arquivo de agentes treinados personalizados na inferência
|
||||
- Corrigir para vincular agentes apenas de tarefa à equipe para arquivos de entrada multimodal
|
||||
- Corrigir para serializar chamadas de guardrail como nulas para checkpointing JSON
|
||||
- Corrigir renomeação de force_final_answer para evitar roteador autorreferencial
|
||||
- Corrigir aumento de litellm para correção de SSTI; ignorar CVE pip não corrigível
|
||||
|
||||
### Documentação
|
||||
- Atualizar changelog e versão para v1.14.4a1
|
||||
- Adicionar página de Ferramentas do Sandbox E2B
|
||||
- Adicionar documentação de ferramentas do sandbox Daytona
|
||||
|
||||
## Contributors
|
||||
|
||||
@EdwardIrby, @dependabot[bot], @factory-droid-oss, @factory-droid[bot], @greysonlalonde, @kunalk16, @lorenzejay, @lucasgomide, @manisrinivasan2k1, @mattatcha, @vinibrsl
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="29 abr 2026">
|
||||
## v1.14.4a1
|
||||
|
||||
|
||||
@@ -193,6 +193,42 @@ Para um controle mais granular, você pode aplicar @persist em métodos específ
|
||||
# (O código não é traduzido)
|
||||
```
|
||||
|
||||
### Forking de Estado Persistido
|
||||
|
||||
`@persist` suporta dois modos distintos de hidratação em `kickoff` / `kickoff_async`:
|
||||
|
||||
- `kickoff(inputs={"id": <uuid>})` — **resume**: carrega o snapshot mais recente do UUID informado e continua escrevendo sob o mesmo `flow_uuid`. O histórico se estende.
|
||||
- `kickoff(restore_from_state_id=<uuid>)` — **fork**: carrega o snapshot mais recente do UUID informado, hidrata o estado da nova execução a partir dele, e atribui um novo `state.id` (auto-gerado, ou `inputs["id"]` se fixado). As escritas do `@persist` da nova execução vão para o novo `state.id`; o histórico do flow de origem é preservado.
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai.flow.persistence import persist
|
||||
from pydantic import BaseModel
|
||||
|
||||
class CounterState(BaseModel):
|
||||
id: str = ""
|
||||
counter: int = 0
|
||||
|
||||
@persist
|
||||
class CounterFlow(Flow[CounterState]):
|
||||
@start()
|
||||
def step(self):
|
||||
self.state.counter += 1
|
||||
print(f"[id={self.state.id}] counter={self.state.counter}")
|
||||
|
||||
# Execução 1: estado novo, counter 0 -> 1, persistido sob flow_1.state.id
|
||||
flow_1 = CounterFlow()
|
||||
flow_1.kickoff()
|
||||
|
||||
# Fork: hidrata do snapshot mais recente de flow_1, mas usa um state.id NOVO
|
||||
flow_2 = CounterFlow()
|
||||
flow_2.kickoff(restore_from_state_id=flow_1.state.id)
|
||||
# flow_2.state.counter começa em 1 (hidratado), e step() incrementa para 2.
|
||||
# flow_2.state.id != flow_1.state.id; o histórico de flow_1 não é alterado.
|
||||
```
|
||||
|
||||
Se o `restore_from_state_id` informado não corresponder a nenhum estado persistido, o kickoff retorna silenciosamente ao comportamento padrão — o mesmo comportamento do `inputs["id"]` quando não encontrado. Combinar `restore_from_state_id` com `from_checkpoint` lança um `ValueError`; escolha uma única fonte de hidratação. Fixar `inputs["id"]` durante o fork compartilha uma chave de persistência com outro flow — geralmente você quer apenas `restore_from_state_id`.
|
||||
|
||||
### Como Funciona
|
||||
|
||||
1. **Identificação Única do Estado**
|
||||
|
||||
@@ -146,6 +146,14 @@ class ProductionFlow(Flow[AppState]):
|
||||
# ...
|
||||
```
|
||||
|
||||
Por padrão, `@persist` retoma um flow quando `kickoff(inputs={"id": <uuid>})` é informado, estendendo o mesmo histórico do `flow_uuid`. Para **forkar** um flow persistido em uma nova linhagem — hidratar o estado a partir de uma execução anterior mas escrever sob um novo `state.id` — passe `restore_from_state_id`:
|
||||
|
||||
```python
|
||||
flow.kickoff(restore_from_state_id="<previous-run-state-id>")
|
||||
```
|
||||
|
||||
A nova execução recebe um novo `state.id` (auto-gerado, ou `inputs["id"]` se fixado), então suas escritas do `@persist` não estendem o histórico da origem. Combinar com `from_checkpoint` lança um `ValueError`; escolha uma única fonte de hidratação.
|
||||
|
||||
## Resumo
|
||||
|
||||
- **Comece com um Flow.**
|
||||
|
||||
@@ -133,7 +133,7 @@ Aqui está uma lista das ferramentas disponíveis e suas descrições:
|
||||
| **DirectorySearchTool** | Ferramenta RAG para busca em diretórios, útil para navegação em sistemas de arquivos. |
|
||||
| **DOCXSearchTool** | Ferramenta RAG voltada para busca em documentos DOCX, ideal para processar arquivos Word. |
|
||||
| **DirectoryReadTool** | Facilita a leitura e processamento de estruturas de diretórios e seus conteúdos. |
|
||||
| **EXASearchTool** | Ferramenta projetada para buscas exaustivas em diversas fontes de dados. |
|
||||
| **ExaSearchTool** | Ferramenta projetada para buscas exaustivas em diversas fontes de dados. |
|
||||
| **FileReadTool** | Permite a leitura e extração de dados de arquivos, suportando diversos formatos. |
|
||||
| **FirecrawlSearchTool** | Ferramenta para buscar páginas web usando Firecrawl e retornar os resultados. |
|
||||
| **FirecrawlCrawlWebsiteTool** | Ferramenta para rastrear páginas web utilizando o Firecrawl. |
|
||||
|
||||
@@ -167,6 +167,48 @@ Para mais controle, você pode aplicar `@persist()` em métodos específicos:
|
||||
# código não traduzido
|
||||
```
|
||||
|
||||
#### Forking de Estado Persistido
|
||||
|
||||
`@persist` suporta dois modos distintos de hidratação em `kickoff` / `kickoff_async`. Use **resume** (`inputs["id"]`) para continuar a mesma linhagem; use **fork** (`restore_from_state_id`) para iniciar uma nova linhagem a partir de um snapshot:
|
||||
|
||||
| | `state.id` após o kickoff | Escritas do `@persist` vão para |
|
||||
|---|---|---|
|
||||
| `inputs["id"]` (resume) | id informado | id informado (estende o histórico) |
|
||||
| `restore_from_state_id` (fork) | id novo, ou `inputs["id"]` se fixado | id novo (origem preservada) |
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai.flow.persistence import persist
|
||||
from pydantic import BaseModel
|
||||
|
||||
class CounterState(BaseModel):
|
||||
id: str = ""
|
||||
counter: int = 0
|
||||
|
||||
@persist
|
||||
class CounterFlow(Flow[CounterState]):
|
||||
@start()
|
||||
def step(self):
|
||||
self.state.counter += 1
|
||||
|
||||
# Execução 1: estado novo, counter 0 -> 1
|
||||
flow_1 = CounterFlow()
|
||||
flow_1.kickoff()
|
||||
|
||||
# Fork: hidrata do snapshot mais recente de flow_1, mas escreve sob um state.id NOVO
|
||||
flow_2 = CounterFlow()
|
||||
flow_2.kickoff(restore_from_state_id=flow_1.state.id)
|
||||
# flow_2 começa com counter=1 (hidratado), e step() incrementa para 2.
|
||||
# O histórico do flow_uuid de flow_1 não é alterado.
|
||||
```
|
||||
|
||||
Notas sobre o comportamento:
|
||||
|
||||
- `restore_from_state_id` não encontrado na persistência → o kickoff retorna silenciosamente ao comportamento padrão (espelha o comportamento de `inputs["id"]` quando não encontrado). Nenhuma exceção é lançada.
|
||||
- Combinar `restore_from_state_id` com `from_checkpoint` lança um `ValueError` — eles miram sistemas de estado diferentes (`@persist` vs. Checkpointing) e não podem ser combinados.
|
||||
- `restore_from_state_id=None` (padrão) é byte-idêntico a um kickoff sem o parâmetro.
|
||||
- Fixar `inputs["id"]` durante o fork significa que a nova execução compartilha uma chave de persistência com outro flow — geralmente você quer apenas `restore_from_state_id`.
|
||||
|
||||
## Padrões Avançados de Estado
|
||||
|
||||
### Lógica Condicional Baseada no Estado
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
---
|
||||
title: Carregador Web EXA Search
|
||||
description: O `EXASearchTool` foi projetado para realizar uma busca semântica para uma consulta especificada a partir do conteúdo de um texto em toda a internet.
|
||||
description: O `ExaSearchTool` foi projetado para realizar uma busca semântica para uma consulta especificada a partir do conteúdo de um texto em toda a internet.
|
||||
icon: globe-pointer
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
# `EXASearchTool`
|
||||
# `ExaSearchTool`
|
||||
|
||||
## Descrição
|
||||
|
||||
O EXASearchTool foi projetado para realizar uma busca semântica para uma consulta especificada a partir do conteúdo de um texto em toda a internet.
|
||||
O ExaSearchTool foi projetado para realizar uma busca semântica para uma consulta especificada a partir do conteúdo de um texto em toda a internet.
|
||||
Ele utiliza a API da [exa.ai](https://exa.ai/) para buscar e exibir os resultados de pesquisa mais relevantes com base na consulta fornecida pelo usuário.
|
||||
|
||||
## Instalação
|
||||
@@ -25,15 +25,15 @@ pip install 'crewai[tools]'
|
||||
O exemplo a seguir demonstra como inicializar a ferramenta e executar uma busca com uma consulta determinada:
|
||||
|
||||
```python Code
|
||||
from crewai_tools import EXASearchTool
|
||||
from crewai_tools import ExaSearchTool
|
||||
|
||||
# Initialize the tool for internet searching capabilities
|
||||
tool = EXASearchTool()
|
||||
tool = ExaSearchTool()
|
||||
```
|
||||
|
||||
## Etapas para Começar
|
||||
|
||||
Para usar o EXASearchTool de forma eficaz, siga estas etapas:
|
||||
Para usar o ExaSearchTool de forma eficaz, siga estas etapas:
|
||||
|
||||
<Steps>
|
||||
<Step title="Instalação do Pacote">
|
||||
@@ -47,7 +47,35 @@ Para usar o EXASearchTool de forma eficaz, siga estas etapas:
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Usando o Exa via MCP
|
||||
|
||||
Você também pode conectar seu agente ao servidor MCP hospedado pelo Exa. Passe sua chave de API no cabeçalho `x-api-key`:
|
||||
|
||||
```python
|
||||
from crewai import Agent
|
||||
from crewai.mcp import MCPServerHTTP
|
||||
|
||||
agent = Agent(
|
||||
role="Research Analyst",
|
||||
goal="Find and analyze information on the web",
|
||||
backstory="Expert researcher with access to Exa's tools",
|
||||
mcps=[
|
||||
MCPServerHTTP(
|
||||
url="https://mcp.exa.ai/mcp",
|
||||
headers={"x-api-key": "YOUR_EXA_API_KEY"},
|
||||
),
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
Obtenha sua chave de API no [painel da Exa](https://dashboard.exa.ai/api-keys). Para mais informações sobre MCP no CrewAI, consulte a [visão geral do MCP](/pt-BR/mcp/overview).
|
||||
|
||||
## Conclusão
|
||||
|
||||
Ao integrar o `EXASearchTool` em projetos Python, os usuários ganham a capacidade de realizar buscas relevantes e em tempo real pela internet diretamente de suas aplicações.
|
||||
Seguindo as orientações de configuração e uso fornecidas, a incorporação desta ferramenta em projetos torna-se simples e direta.
|
||||
Ao integrar o `ExaSearchTool` em projetos Python, os usuários ganham a capacidade de realizar buscas relevantes e em tempo real pela internet diretamente de suas aplicações.
|
||||
Seguindo as orientações de configuração e uso fornecidas, a incorporação desta ferramenta em projetos torna-se simples e direta.
|
||||
|
||||
## Recursos
|
||||
|
||||
- [Documentação do Exa](https://exa.ai/docs)
|
||||
- [Painel do Exa — gerenciar chaves de API e uso](https://dashboard.exa.ai)
|
||||
26
lib/cli/README.md
Normal file
26
lib/cli/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# crewai-cli
|
||||
|
||||
CLI for CrewAI — scaffold, run, deploy and manage AI agent crews without
|
||||
installing the full framework.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install crewai-cli
|
||||
```
|
||||
|
||||
This pulls in `crewai-core` (shared utilities) but not the `crewai` framework
|
||||
itself, so commands that don't need a crew loaded — `crewai version`,
|
||||
`crewai login`, `crewai org list`, `crewai config *`, `crewai traces *`,
|
||||
`crewai create`, `crewai template *` — work standalone.
|
||||
|
||||
Commands that load a user's crew or flow (`crewai run`, `crewai train`,
|
||||
`crewai test`, `crewai chat`, `crewai replay`, `crewai reset-memories`,
|
||||
`crewai deploy push`, `crewai tool publish`) require `crewai` to be installed
|
||||
in the project's environment. They print a clear error if it is missing.
|
||||
|
||||
To install both at once:
|
||||
|
||||
```bash
|
||||
pip install crewai[cli]
|
||||
```
|
||||
45
lib/cli/pyproject.toml
Normal file
45
lib/cli/pyproject.toml
Normal file
@@ -0,0 +1,45 @@
|
||||
[project]
|
||||
name = "crewai-cli"
|
||||
dynamic = ["version"]
|
||||
description = "CLI for CrewAI — scaffold, run, deploy and manage AI agent crews."
|
||||
readme = "README.md"
|
||||
authors = [
|
||||
{ name = "Joao Moura", email = "joao@crewai.com" }
|
||||
]
|
||||
requires-python = ">=3.10, <3.14"
|
||||
dependencies = [
|
||||
"crewai-core==1.14.5a3",
|
||||
"click~=8.1.7",
|
||||
"pydantic>=2.11.9,<2.13",
|
||||
"pydantic-settings~=2.10.1",
|
||||
"appdirs~=1.4.4",
|
||||
"cryptography>=42.0",
|
||||
"httpx~=0.28.1",
|
||||
"pyjwt>=2.9.0,<3",
|
||||
"rich>=13.7.1",
|
||||
"tomli~=2.0.2",
|
||||
"tomli-w~=1.1.0",
|
||||
"packaging>=23.0",
|
||||
"python-dotenv>=1.2.2,<2",
|
||||
"uv~=0.11.6",
|
||||
"textual>=7.5.0",
|
||||
"certifi",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://crewai.com"
|
||||
Documentation = "https://docs.crewai.com"
|
||||
Repository = "https://github.com/crewAIInc/crewAI"
|
||||
|
||||
[project.scripts]
|
||||
crewai = "crewai_cli.cli:crewai"
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.hatch.version]
|
||||
path = "src/crewai_cli/__init__.py"
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["src/crewai_cli"]
|
||||
1
lib/cli/src/crewai_cli/__init__.py
Normal file
1
lib/cli/src/crewai_cli/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
__version__ = "1.14.5a3"
|
||||
@@ -1,9 +1,9 @@
|
||||
from pathlib import Path
|
||||
|
||||
import click
|
||||
from crewai_core.printer import PRINTER
|
||||
|
||||
from crewai.cli.utils import copy_template
|
||||
from crewai.utilities.printer import PRINTER
|
||||
from crewai_cli.utils import copy_template
|
||||
|
||||
|
||||
def add_crew_to_flow(crew_name: str) -> None:
|
||||
8
lib/cli/src/crewai_cli/authentication/__init__.py
Normal file
8
lib/cli/src/crewai_cli/authentication/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
"""CLI authentication entry point."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_cli.authentication.main import AuthenticationCommand
|
||||
|
||||
|
||||
__all__ = ["AuthenticationCommand"]
|
||||
8
lib/cli/src/crewai_cli/authentication/constants.py
Normal file
8
lib/cli/src/crewai_cli/authentication/constants.py
Normal file
@@ -0,0 +1,8 @@
|
||||
"""Re-export of authentication constants from ``crewai_core.auth.constants``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.auth.constants import ALGORITHMS as ALGORITHMS
|
||||
|
||||
|
||||
__all__ = ["ALGORITHMS"]
|
||||
60
lib/cli/src/crewai_cli/authentication/main.py
Normal file
60
lib/cli/src/crewai_cli/authentication/main.py
Normal file
@@ -0,0 +1,60 @@
|
||||
"""CLI-side authentication wiring.
|
||||
|
||||
Re-exports the OAuth2 primitives from ``crewai_core.auth`` and overrides the
|
||||
``_post_login`` hook to also log into the tool repository.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.auth.oauth2 import (
|
||||
AuthenticationCommand as _BaseAuthenticationCommand,
|
||||
Oauth2Settings as Oauth2Settings,
|
||||
ProviderFactory as ProviderFactory,
|
||||
console,
|
||||
)
|
||||
from crewai_core.settings import Settings
|
||||
|
||||
|
||||
__all__ = ["AuthenticationCommand", "Oauth2Settings", "ProviderFactory"]
|
||||
|
||||
|
||||
class AuthenticationCommand(_BaseAuthenticationCommand):
|
||||
"""CLI-side login that also signs the user into the tool repository."""
|
||||
|
||||
def _post_login(self) -> None:
|
||||
self._login_to_tool_repository()
|
||||
|
||||
def _login_to_tool_repository(self) -> None:
|
||||
from crewai_cli.tools.main import ToolCommand
|
||||
|
||||
try:
|
||||
console.print(
|
||||
"Now logging you in to the Tool Repository... ",
|
||||
style="bold blue",
|
||||
end="",
|
||||
)
|
||||
|
||||
ToolCommand().login()
|
||||
|
||||
console.print(
|
||||
"Success!\n",
|
||||
style="bold green",
|
||||
)
|
||||
|
||||
settings = Settings()
|
||||
|
||||
console.print(
|
||||
f"You are now authenticated to the tool repository for organization [bold cyan]'{settings.org_name if settings.org_name else settings.org_uuid}'[/bold cyan]",
|
||||
style="green",
|
||||
)
|
||||
except (Exception, SystemExit):
|
||||
console.print(
|
||||
"\n[bold yellow]Warning:[/bold yellow] Authentication with the Tool Repository failed.",
|
||||
style="yellow",
|
||||
)
|
||||
console.print(
|
||||
"Other features will work normally, but you may experience limitations "
|
||||
"with downloading and publishing tools."
|
||||
"\nRun [bold]crewai login[/bold] to try logging in again.\n",
|
||||
style="yellow",
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
"""OAuth2 authentication providers — re-exported from ``crewai_core.auth.providers``."""
|
||||
8
lib/cli/src/crewai_cli/authentication/providers/auth0.py
Normal file
8
lib/cli/src/crewai_cli/authentication/providers/auth0.py
Normal file
@@ -0,0 +1,8 @@
|
||||
"""Re-export of ``Auth0Provider`` from ``crewai_core.auth.providers.auth0``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.auth.providers.auth0 import Auth0Provider as Auth0Provider
|
||||
|
||||
|
||||
__all__ = ["Auth0Provider"]
|
||||
@@ -0,0 +1,8 @@
|
||||
"""Re-export of ``BaseProvider`` from ``crewai_core.auth.providers.base_provider``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.auth.providers.base_provider import BaseProvider as BaseProvider
|
||||
|
||||
|
||||
__all__ = ["BaseProvider"]
|
||||
@@ -0,0 +1,8 @@
|
||||
"""Re-export of ``EntraIdProvider`` from ``crewai_core.auth.providers.entra_id``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.auth.providers.entra_id import EntraIdProvider as EntraIdProvider
|
||||
|
||||
|
||||
__all__ = ["EntraIdProvider"]
|
||||
@@ -0,0 +1,8 @@
|
||||
"""Re-export of ``KeycloakProvider`` from ``crewai_core.auth.providers.keycloak``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.auth.providers.keycloak import KeycloakProvider as KeycloakProvider
|
||||
|
||||
|
||||
__all__ = ["KeycloakProvider"]
|
||||
8
lib/cli/src/crewai_cli/authentication/providers/okta.py
Normal file
8
lib/cli/src/crewai_cli/authentication/providers/okta.py
Normal file
@@ -0,0 +1,8 @@
|
||||
"""Re-export of ``OktaProvider`` from ``crewai_core.auth.providers.okta``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.auth.providers.okta import OktaProvider as OktaProvider
|
||||
|
||||
|
||||
__all__ = ["OktaProvider"]
|
||||
@@ -0,0 +1,8 @@
|
||||
"""Re-export of ``WorkosProvider`` from ``crewai_core.auth.providers.workos``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.auth.providers.workos import WorkosProvider as WorkosProvider
|
||||
|
||||
|
||||
__all__ = ["WorkosProvider"]
|
||||
11
lib/cli/src/crewai_cli/authentication/token.py
Normal file
11
lib/cli/src/crewai_cli/authentication/token.py
Normal file
@@ -0,0 +1,11 @@
|
||||
"""Re-exports of authentication token helpers from ``crewai_core.auth.token``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.auth.token import (
|
||||
AuthError as AuthError,
|
||||
get_auth_token as get_auth_token,
|
||||
)
|
||||
|
||||
|
||||
__all__ = ["AuthError", "get_auth_token"]
|
||||
8
lib/cli/src/crewai_cli/authentication/utils.py
Normal file
8
lib/cli/src/crewai_cli/authentication/utils.py
Normal file
@@ -0,0 +1,8 @@
|
||||
"""Re-export of ``validate_jwt_token`` from ``crewai_core.auth.utils``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.auth.utils import validate_jwt_token as validate_jwt_token
|
||||
|
||||
|
||||
__all__ = ["validate_jwt_token"]
|
||||
@@ -21,7 +21,7 @@ from textual.widgets import (
|
||||
Tree,
|
||||
)
|
||||
|
||||
from crewai.cli.checkpoint_cli import (
|
||||
from crewai_cli.checkpoint_cli import (
|
||||
_format_size,
|
||||
_is_sqlite,
|
||||
_list_json,
|
||||
@@ -1,50 +1,66 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from importlib.metadata import version as get_version
|
||||
import os
|
||||
import subprocess
|
||||
from typing import Any
|
||||
|
||||
import click
|
||||
from crewai_core.token_manager import TokenManager
|
||||
|
||||
from crewai.cli.add_crew_to_flow import add_crew_to_flow
|
||||
from crewai.cli.authentication.main import AuthenticationCommand
|
||||
from crewai.cli.config import Settings
|
||||
from crewai.cli.create_crew import create_crew
|
||||
from crewai.cli.create_flow import create_flow
|
||||
from crewai.cli.crew_chat import run_chat
|
||||
from crewai.cli.deploy.main import DeployCommand
|
||||
from crewai.cli.enterprise.main import EnterpriseConfigureCommand
|
||||
from crewai.cli.evaluate_crew import evaluate_crew
|
||||
from crewai.cli.install_crew import install_crew
|
||||
from crewai.cli.kickoff_flow import kickoff_flow
|
||||
from crewai.cli.organization.main import OrganizationCommand
|
||||
from crewai.cli.plot_flow import plot_flow
|
||||
from crewai.cli.remote_template.main import TemplateCommand
|
||||
from crewai.cli.replay_from_task import replay_task_command
|
||||
from crewai.cli.reset_memories_command import reset_memories_command
|
||||
from crewai.cli.run_crew import run_crew
|
||||
from crewai.cli.settings.main import SettingsCommand
|
||||
from crewai.cli.shared.token_manager import TokenManager
|
||||
from crewai.cli.tools.main import ToolCommand
|
||||
from crewai.cli.train_crew import train_crew
|
||||
from crewai.cli.triggers.main import TriggersCommand
|
||||
from crewai.cli.update_crew import update_crew
|
||||
from crewai.cli.utils import build_env_with_all_tool_credentials, read_toml
|
||||
from crewai.memory.storage.kickoff_task_outputs_storage import (
|
||||
KickoffTaskOutputsSQLiteStorage,
|
||||
from crewai_cli.add_crew_to_flow import add_crew_to_flow
|
||||
from crewai_cli.authentication.main import AuthenticationCommand
|
||||
from crewai_cli.config import Settings
|
||||
from crewai_cli.create_crew import create_crew
|
||||
from crewai_cli.create_flow import create_flow
|
||||
from crewai_cli.crew_chat import run_chat
|
||||
from crewai_cli.deploy.main import DeployCommand
|
||||
from crewai_cli.enterprise.main import EnterpriseConfigureCommand
|
||||
from crewai_cli.evaluate_crew import evaluate_crew
|
||||
from crewai_cli.install_crew import install_crew
|
||||
from crewai_cli.kickoff_flow import kickoff_flow
|
||||
from crewai_cli.organization.main import OrganizationCommand
|
||||
from crewai_cli.plot_flow import plot_flow
|
||||
from crewai_cli.remote_template.main import TemplateCommand
|
||||
from crewai_cli.replay_from_task import replay_task_command
|
||||
from crewai_cli.reset_memories_command import reset_memories_command
|
||||
from crewai_cli.run_crew import run_crew
|
||||
from crewai_cli.settings.main import SettingsCommand
|
||||
from crewai_cli.task_outputs import load_task_outputs
|
||||
from crewai_cli.tools.main import ToolCommand
|
||||
from crewai_cli.train_crew import train_crew
|
||||
from crewai_cli.triggers.main import TriggersCommand
|
||||
from crewai_cli.update_crew import update_crew
|
||||
from crewai_cli.user_data import (
|
||||
_load_user_data,
|
||||
is_tracing_enabled,
|
||||
update_user_data,
|
||||
)
|
||||
from crewai_cli.utils import build_env_with_all_tool_credentials, read_toml
|
||||
|
||||
|
||||
def _get_cli_version() -> str:
|
||||
"""Return the best available version string for the CLI."""
|
||||
# Prefer crewai version if installed (keeps existing UX)
|
||||
try:
|
||||
return get_version("crewai")
|
||||
except Exception: # noqa: S110
|
||||
pass
|
||||
try:
|
||||
return get_version("crewai-cli")
|
||||
except Exception:
|
||||
return "unknown"
|
||||
|
||||
|
||||
@click.group()
|
||||
@click.version_option(get_version("crewai"))
|
||||
@click.version_option(_get_cli_version())
|
||||
def crewai() -> None:
|
||||
"""Top-level command group for crewai."""
|
||||
|
||||
|
||||
@crewai.command(
|
||||
name="uv",
|
||||
context_settings=dict(
|
||||
ignore_unknown_options=True,
|
||||
),
|
||||
context_settings={"ignore_unknown_options": True},
|
||||
)
|
||||
@click.argument("uv_args", nargs=-1, type=click.UNPROCESSED)
|
||||
def uv(uv_args: tuple[str, ...]) -> None:
|
||||
@@ -105,7 +121,7 @@ def version(tools: bool) -> None:
|
||||
|
||||
if tools:
|
||||
try:
|
||||
tools_version = get_version("crewai")
|
||||
tools_version = get_version("crewai-tools")
|
||||
click.echo(f"crewai tools version: {tools_version}")
|
||||
except Exception:
|
||||
click.echo("crewai tools not installed")
|
||||
@@ -168,12 +184,9 @@ def replay(task_id: str, trained_agents_file: str | None) -> None:
|
||||
|
||||
@crewai.command()
|
||||
def log_tasks_outputs() -> None:
|
||||
"""
|
||||
Retrieve your latest crew.kickoff() task outputs.
|
||||
"""
|
||||
"""Retrieve your latest crew.kickoff() task outputs."""
|
||||
try:
|
||||
storage = KickoffTaskOutputsSQLiteStorage()
|
||||
tasks = storage.load()
|
||||
tasks = load_task_outputs()
|
||||
|
||||
if not tasks:
|
||||
click.echo(
|
||||
@@ -231,11 +244,8 @@ def reset_memories(
|
||||
agent_knowledge: bool,
|
||||
all: bool,
|
||||
) -> None:
|
||||
"""
|
||||
Reset the crew memories (memory, knowledge, agent_knowledge, kickoff_outputs). This will delete all the data saved.
|
||||
"""
|
||||
"""Reset the crew memories (memory, knowledge, agent_knowledge, kickoff_outputs). This will delete all the data saved."""
|
||||
try:
|
||||
# Treat legacy flags as --memory with a deprecation warning
|
||||
if long or short or entities:
|
||||
legacy_used = [
|
||||
f
|
||||
@@ -302,7 +312,7 @@ def memory(
|
||||
) -> None:
|
||||
"""Open the Memory TUI to browse scopes and recall memories."""
|
||||
try:
|
||||
from crewai.cli.memory_tui import MemoryTUI
|
||||
from crewai_cli.memory_tui import MemoryTUI
|
||||
except ImportError as exc:
|
||||
click.echo(
|
||||
"Textual is required for the memory TUI but could not be imported. "
|
||||
@@ -365,10 +375,10 @@ def test(n_iterations: int, model: str, trained_agents_file: str | None) -> None
|
||||
|
||||
|
||||
@crewai.command(
|
||||
context_settings=dict(
|
||||
ignore_unknown_options=True,
|
||||
allow_extra_args=True,
|
||||
)
|
||||
context_settings={
|
||||
"ignore_unknown_options": True,
|
||||
"allow_extra_args": True,
|
||||
}
|
||||
)
|
||||
@click.pass_context
|
||||
def install(context: click.Context) -> None:
|
||||
@@ -471,7 +481,7 @@ def deploy_validate() -> None:
|
||||
`crewai deploy push` run automatically, without contacting the platform.
|
||||
Exits non-zero if any blocking issues are found.
|
||||
"""
|
||||
from crewai.cli.deploy.validate import run_validate_command
|
||||
from crewai_cli.deploy.validate import run_validate_command
|
||||
|
||||
run_validate_command()
|
||||
|
||||
@@ -612,14 +622,12 @@ def triggers_run(trigger_path: str) -> None:
|
||||
|
||||
@crewai.command()
|
||||
def chat() -> None:
|
||||
"""
|
||||
Start a conversation with the Crew, collecting user-supplied inputs,
|
||||
"""Start a conversation with the Crew, collecting user-supplied inputs,
|
||||
and using the Chat LLM to generate responses.
|
||||
"""
|
||||
click.secho(
|
||||
"\nStarting a conversation with the Crew\nType 'exit' or Ctrl+C to quit.\n",
|
||||
)
|
||||
|
||||
run_chat()
|
||||
|
||||
|
||||
@@ -784,16 +792,14 @@ def traces_enable() -> None:
|
||||
from rich.console import Console
|
||||
from rich.panel import Panel
|
||||
|
||||
from crewai.events.listeners.tracing.utils import update_user_data
|
||||
|
||||
console = Console()
|
||||
|
||||
update_user_data({"trace_consent": True, "first_execution_done": True})
|
||||
|
||||
panel = Panel(
|
||||
"✅ Trace collection has been enabled!\n\n"
|
||||
"✅ Trace collection enabled.\n\n"
|
||||
"Your crew/flow executions will now send traces to CrewAI+.\n"
|
||||
"Use 'crewai traces disable' to turn off trace collection.",
|
||||
"Use 'crewai traces disable' to opt out.",
|
||||
title="Traces Enabled",
|
||||
border_style="green",
|
||||
padding=(1, 2),
|
||||
@@ -807,16 +813,16 @@ def traces_disable() -> None:
|
||||
from rich.console import Console
|
||||
from rich.panel import Panel
|
||||
|
||||
from crewai.events.listeners.tracing.utils import update_user_data
|
||||
|
||||
console = Console()
|
||||
|
||||
update_user_data({"trace_consent": False, "first_execution_done": True})
|
||||
|
||||
panel = Panel(
|
||||
"❌ Trace collection has been disabled!\n\n"
|
||||
"Your crew/flow executions will no longer send traces.\n"
|
||||
"Use 'crewai traces enable' to turn trace collection back on.",
|
||||
"❌ Trace collection disabled.\n\n"
|
||||
"Your crew/flow executions will no longer send traces "
|
||||
"(unless [bold]CREWAI_TRACING_ENABLED=true[/bold] is set in the environment, "
|
||||
"which overrides the opt-out).\n"
|
||||
"Use 'crewai traces enable' to opt back in.",
|
||||
title="Traces Disabled",
|
||||
border_style="red",
|
||||
padding=(1, 2),
|
||||
@@ -832,11 +838,6 @@ def traces_status() -> None:
|
||||
from rich.panel import Panel
|
||||
from rich.table import Table
|
||||
|
||||
from crewai.events.listeners.tracing.utils import (
|
||||
_load_user_data,
|
||||
is_tracing_enabled,
|
||||
)
|
||||
|
||||
console = Console()
|
||||
user_data = _load_user_data()
|
||||
|
||||
@@ -883,13 +884,13 @@ def traces_status() -> None:
|
||||
@click.pass_context
|
||||
def checkpoint(ctx: click.Context, location: str) -> None:
|
||||
"""Browse and inspect checkpoints. Launches a TUI when called without a subcommand."""
|
||||
from crewai.cli.checkpoint_cli import _detect_location
|
||||
from crewai_cli.checkpoint_cli import _detect_location
|
||||
|
||||
location = _detect_location(location)
|
||||
ctx.ensure_object(dict)
|
||||
ctx.obj["location"] = location
|
||||
if ctx.invoked_subcommand is None:
|
||||
from crewai.cli.checkpoint_tui import run_checkpoint_tui
|
||||
from crewai_cli.checkpoint_tui import run_checkpoint_tui
|
||||
|
||||
run_checkpoint_tui(location)
|
||||
|
||||
@@ -898,7 +899,7 @@ def checkpoint(ctx: click.Context, location: str) -> None:
|
||||
@click.argument("location", default="./.checkpoints")
|
||||
def checkpoint_list(location: str) -> None:
|
||||
"""List checkpoints in a directory."""
|
||||
from crewai.cli.checkpoint_cli import _detect_location, list_checkpoints
|
||||
from crewai_cli.checkpoint_cli import _detect_location, list_checkpoints
|
||||
|
||||
list_checkpoints(_detect_location(location))
|
||||
|
||||
@@ -907,7 +908,7 @@ def checkpoint_list(location: str) -> None:
|
||||
@click.argument("path", default="./.checkpoints")
|
||||
def checkpoint_info(path: str) -> None:
|
||||
"""Show details of a checkpoint. Pass a file or directory for latest."""
|
||||
from crewai.cli.checkpoint_cli import _detect_location, info_checkpoint
|
||||
from crewai_cli.checkpoint_cli import _detect_location, info_checkpoint
|
||||
|
||||
info_checkpoint(_detect_location(path))
|
||||
|
||||
@@ -917,7 +918,7 @@ def checkpoint_info(path: str) -> None:
|
||||
@click.pass_context
|
||||
def checkpoint_resume(ctx: click.Context, checkpoint_id: str | None) -> None:
|
||||
"""Resume from a checkpoint. Defaults to the most recent."""
|
||||
from crewai.cli.checkpoint_cli import resume_checkpoint
|
||||
from crewai_cli.checkpoint_cli import resume_checkpoint
|
||||
|
||||
resume_checkpoint(ctx.obj["location"], checkpoint_id)
|
||||
|
||||
@@ -928,7 +929,7 @@ def checkpoint_resume(ctx: click.Context, checkpoint_id: str | None) -> None:
|
||||
@click.pass_context
|
||||
def checkpoint_diff(ctx: click.Context, id1: str, id2: str) -> None:
|
||||
"""Compare two checkpoints side-by-side."""
|
||||
from crewai.cli.checkpoint_cli import diff_checkpoints
|
||||
from crewai_cli.checkpoint_cli import diff_checkpoints
|
||||
|
||||
diff_checkpoints(ctx.obj["location"], id1, id2)
|
||||
|
||||
@@ -950,7 +951,7 @@ def checkpoint_prune(
|
||||
ctx: click.Context, keep: int | None, older_than: str | None, dry_run: bool
|
||||
) -> None:
|
||||
"""Remove old checkpoints."""
|
||||
from crewai.cli.checkpoint_cli import prune_checkpoints
|
||||
from crewai_cli.checkpoint_cli import prune_checkpoints
|
||||
|
||||
prune_checkpoints(ctx.obj["location"], keep, older_than, dry_run)
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
from crewai_core.telemetry import Telemetry
|
||||
import httpx
|
||||
from rich.console import Console
|
||||
|
||||
from crewai.cli.authentication.token import get_auth_token
|
||||
from crewai.cli.plus_api import PlusAPI
|
||||
from crewai.telemetry.telemetry import Telemetry
|
||||
from crewai_cli.authentication.token import get_auth_token
|
||||
from crewai_cli.plus_api import PlusAPI
|
||||
|
||||
|
||||
console = Console()
|
||||
@@ -32,11 +34,10 @@ class PlusAPIMixin:
|
||||
raise SystemExit from None
|
||||
|
||||
def _validate_response(self, response: httpx.Response) -> None:
|
||||
"""
|
||||
Handle and display error messages from API responses.
|
||||
"""Handle and display error messages from API responses.
|
||||
|
||||
Args:
|
||||
response (httpx.Response): The response from the Plus API
|
||||
response: The response from the Plus API.
|
||||
"""
|
||||
try:
|
||||
json_response = response.json()
|
||||
30
lib/cli/src/crewai_cli/config.py
Normal file
30
lib/cli/src/crewai_cli/config.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""Re-exports of shared settings from ``crewai_core.settings``.
|
||||
|
||||
Kept as a stable import path for the CLI; new code should import from
|
||||
``crewai_core.settings`` directly.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.settings import (
|
||||
CLI_SETTINGS_KEYS as CLI_SETTINGS_KEYS,
|
||||
DEFAULT_CLI_SETTINGS as DEFAULT_CLI_SETTINGS,
|
||||
DEFAULT_CONFIG_PATH as DEFAULT_CONFIG_PATH,
|
||||
HIDDEN_SETTINGS_KEYS as HIDDEN_SETTINGS_KEYS,
|
||||
READONLY_SETTINGS_KEYS as READONLY_SETTINGS_KEYS,
|
||||
USER_SETTINGS_KEYS as USER_SETTINGS_KEYS,
|
||||
Settings as Settings,
|
||||
get_writable_config_path as get_writable_config_path,
|
||||
)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"CLI_SETTINGS_KEYS",
|
||||
"DEFAULT_CLI_SETTINGS",
|
||||
"DEFAULT_CONFIG_PATH",
|
||||
"HIDDEN_SETTINGS_KEYS",
|
||||
"READONLY_SETTINGS_KEYS",
|
||||
"USER_SETTINGS_KEYS",
|
||||
"Settings",
|
||||
"get_writable_config_path",
|
||||
]
|
||||
@@ -5,13 +5,13 @@ import sys
|
||||
import click
|
||||
import tomli
|
||||
|
||||
from crewai.cli.constants import ENV_VARS, MODELS
|
||||
from crewai.cli.provider import (
|
||||
from crewai_cli.constants import ENV_VARS, MODELS
|
||||
from crewai_cli.provider import (
|
||||
get_provider_data,
|
||||
select_model,
|
||||
select_provider,
|
||||
)
|
||||
from crewai.cli.utils import copy_template, load_env_vars, write_env_file
|
||||
from crewai_cli.utils import copy_template, load_env_vars, write_env_file
|
||||
|
||||
|
||||
def get_reserved_script_names() -> set[str]:
|
||||
@@ -2,8 +2,7 @@ from pathlib import Path
|
||||
import shutil
|
||||
|
||||
import click
|
||||
|
||||
from crewai.telemetry import Telemetry
|
||||
from crewai_core.telemetry import Telemetry
|
||||
|
||||
|
||||
def create_flow(name: str) -> None:
|
||||
@@ -18,7 +17,6 @@ def create_flow(name: str) -> None:
|
||||
click.secho(f"Error: Folder {folder_name} already exists.", fg="red")
|
||||
return
|
||||
|
||||
# Initialize telemetry
|
||||
telemetry = Telemetry()
|
||||
telemetry.flow_creation_span(class_name)
|
||||
|
||||
23
lib/cli/src/crewai_cli/crew_chat.py
Normal file
23
lib/cli/src/crewai_cli/crew_chat.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""Wrapper for the crew chat command.
|
||||
|
||||
Delegates to ``crewai.utilities.crew_chat.run_chat`` when the full crewai
|
||||
package is installed, otherwise prints a helpful error message.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import click
|
||||
|
||||
|
||||
def run_chat() -> None:
|
||||
try:
|
||||
from crewai.utilities.crew_chat import run_chat as _run_chat
|
||||
except ImportError:
|
||||
click.secho(
|
||||
"The 'chat' command requires the full crewai package.\n"
|
||||
"Install it with: pip install crewai",
|
||||
fg="red",
|
||||
)
|
||||
raise SystemExit(1) from None
|
||||
|
||||
_run_chat()
|
||||
@@ -2,10 +2,10 @@ from typing import Any
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
from crewai.cli import git
|
||||
from crewai.cli.command import BaseCommand, PlusAPIMixin
|
||||
from crewai.cli.deploy.validate import validate_project
|
||||
from crewai.cli.utils import fetch_and_json_env_file, get_project_name
|
||||
from crewai_cli import git
|
||||
from crewai_cli.command import BaseCommand, PlusAPIMixin
|
||||
from crewai_cli.deploy.validate import validate_project
|
||||
from crewai_cli.utils import fetch_and_json_env_file, get_project_name
|
||||
|
||||
|
||||
console = Console()
|
||||
@@ -40,7 +40,7 @@ from typing import Any
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
from crewai.cli.utils import parse_toml
|
||||
from crewai_cli.utils import parse_toml
|
||||
|
||||
|
||||
console = Console()
|
||||
@@ -438,7 +438,7 @@ class DeployValidator:
|
||||
"import json, sys, traceback, os\n"
|
||||
"os.chdir(sys.argv[1])\n"
|
||||
"try:\n"
|
||||
" from crewai.cli.utils import get_crews, get_flows\n"
|
||||
" from crewai.utilities.project_utils import get_crews, get_flows\n"
|
||||
" is_flow = sys.argv[2] == 'flow'\n"
|
||||
" if is_flow:\n"
|
||||
" instances = get_flows()\n"
|
||||
@@ -4,10 +4,10 @@ from typing import Any, cast
|
||||
import httpx
|
||||
from rich.console import Console
|
||||
|
||||
from crewai.cli.authentication.main import Oauth2Settings, ProviderFactory
|
||||
from crewai.cli.command import BaseCommand
|
||||
from crewai.cli.settings.main import SettingsCommand
|
||||
from crewai.utilities.version import get_crewai_version
|
||||
from crewai_cli.authentication.main import Oauth2Settings, ProviderFactory
|
||||
from crewai_cli.command import BaseCommand
|
||||
from crewai_cli.settings.main import SettingsCommand
|
||||
from crewai_cli.version import get_crewai_version
|
||||
|
||||
|
||||
console = Console()
|
||||
@@ -1,9 +1,9 @@
|
||||
import subprocess
|
||||
|
||||
import click
|
||||
from crewai_core.constants import CREWAI_TRAINED_AGENTS_FILE_ENV
|
||||
|
||||
from crewai.cli.utils import build_env_with_all_tool_credentials
|
||||
from crewai.utilities.constants import CREWAI_TRAINED_AGENTS_FILE_ENV
|
||||
from crewai_cli.utils import build_env_with_all_tool_credentials
|
||||
|
||||
|
||||
def evaluate_crew(
|
||||
@@ -2,7 +2,7 @@ import subprocess
|
||||
|
||||
import click
|
||||
|
||||
from crewai.cli.utils import build_env_with_all_tool_credentials
|
||||
from crewai_cli.utils import build_env_with_all_tool_credentials
|
||||
|
||||
|
||||
# Be mindful about changing this.
|
||||
@@ -2,8 +2,8 @@ from httpx import HTTPStatusError
|
||||
from rich.console import Console
|
||||
from rich.table import Table
|
||||
|
||||
from crewai.cli.command import BaseCommand, PlusAPIMixin
|
||||
from crewai.cli.config import Settings
|
||||
from crewai_cli.command import BaseCommand, PlusAPIMixin
|
||||
from crewai_cli.config import Settings
|
||||
|
||||
|
||||
console = Console()
|
||||
12
lib/cli/src/crewai_cli/plus_api.py
Normal file
12
lib/cli/src/crewai_cli/plus_api.py
Normal file
@@ -0,0 +1,12 @@
|
||||
"""Re-export of ``crewai_core.plus_api.PlusAPI``.
|
||||
|
||||
Kept as a stable import path for the CLI; new code should import from
|
||||
``crewai_core.plus_api`` directly.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.plus_api import PlusAPI as PlusAPI
|
||||
|
||||
|
||||
__all__ = ["PlusAPI"]
|
||||
@@ -10,7 +10,7 @@ import certifi
|
||||
import click
|
||||
import httpx
|
||||
|
||||
from crewai.cli.constants import JSON_URL, MODELS, PROVIDERS
|
||||
from crewai_cli.constants import JSON_URL, MODELS, PROVIDERS
|
||||
|
||||
|
||||
def select_choice(prompt_message: str, choices: Sequence[str]) -> str | None:
|
||||
@@ -11,7 +11,7 @@ from rich.console import Console
|
||||
from rich.panel import Panel
|
||||
from rich.text import Text
|
||||
|
||||
from crewai.cli.command import BaseCommand
|
||||
from crewai_cli.command import BaseCommand
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -1,9 +1,9 @@
|
||||
import subprocess
|
||||
|
||||
import click
|
||||
from crewai_core.constants import CREWAI_TRAINED_AGENTS_FILE_ENV
|
||||
|
||||
from crewai.cli.utils import build_env_with_all_tool_credentials
|
||||
from crewai.utilities.constants import CREWAI_TRAINED_AGENTS_FILE_ENV
|
||||
from crewai_cli.utils import build_env_with_all_tool_credentials
|
||||
|
||||
|
||||
def replay_task_command(task_id: str, trained_agents_file: str | None = None) -> None:
|
||||
31
lib/cli/src/crewai_cli/reset_memories_command.py
Normal file
31
lib/cli/src/crewai_cli/reset_memories_command.py
Normal file
@@ -0,0 +1,31 @@
|
||||
"""Wrapper for the reset-memories command.
|
||||
|
||||
Delegates to ``crewai.utilities.reset_memories`` when the full crewai
|
||||
package is installed, otherwise prints a helpful error message.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import click
|
||||
|
||||
|
||||
def reset_memories_command(
|
||||
memory: bool,
|
||||
knowledge: bool,
|
||||
agent_knowledge: bool,
|
||||
kickoff_outputs: bool,
|
||||
all: bool,
|
||||
) -> None:
|
||||
try:
|
||||
from crewai.utilities.reset_memories import (
|
||||
reset_memories_command as _reset,
|
||||
)
|
||||
except ImportError:
|
||||
click.secho(
|
||||
"The 'reset-memories' command requires the full crewai package.\n"
|
||||
"Install it with: pip install crewai",
|
||||
fg="red",
|
||||
)
|
||||
raise SystemExit(1) from None
|
||||
|
||||
_reset(memory, knowledge, agent_knowledge, kickoff_outputs, all)
|
||||
@@ -2,11 +2,11 @@ from enum import Enum
|
||||
import subprocess
|
||||
|
||||
import click
|
||||
from crewai_core.constants import CREWAI_TRAINED_AGENTS_FILE_ENV
|
||||
from packaging import version
|
||||
|
||||
from crewai.cli.utils import build_env_with_all_tool_credentials, read_toml
|
||||
from crewai.utilities.constants import CREWAI_TRAINED_AGENTS_FILE_ENV
|
||||
from crewai.utilities.version import get_crewai_version
|
||||
from crewai_cli.utils import build_env_with_all_tool_credentials, read_toml
|
||||
from crewai_cli.version import get_crewai_version
|
||||
|
||||
|
||||
class CrewType(Enum):
|
||||
@@ -5,9 +5,9 @@ from typing import Any
|
||||
from rich.console import Console
|
||||
from rich.table import Table
|
||||
|
||||
from crewai.cli.command import BaseCommand
|
||||
from crewai.cli.config import HIDDEN_SETTINGS_KEYS, READONLY_SETTINGS_KEYS, Settings
|
||||
from crewai.events.listeners.tracing.utils import _load_user_data
|
||||
from crewai_cli.command import BaseCommand
|
||||
from crewai_cli.config import HIDDEN_SETTINGS_KEYS, READONLY_SETTINGS_KEYS, Settings
|
||||
from crewai_cli.user_data import _load_user_data
|
||||
|
||||
|
||||
console = Console()
|
||||
@@ -91,7 +91,7 @@ class SettingsCommand(BaseCommand):
|
||||
style="bold red",
|
||||
)
|
||||
console.print("Available keys:", style="yellow")
|
||||
for field_name in Settings.model_fields.keys():
|
||||
for field_name in Settings.model_fields:
|
||||
if field_name not in readonly_settings:
|
||||
console.print(f" - {field_name}", style="yellow")
|
||||
raise SystemExit(1)
|
||||
12
lib/cli/src/crewai_cli/shared/token_manager.py
Normal file
12
lib/cli/src/crewai_cli/shared/token_manager.py
Normal file
@@ -0,0 +1,12 @@
|
||||
"""Re-export of ``crewai_core.token_manager.TokenManager``.
|
||||
|
||||
Kept as a stable import path for the CLI; new code should import from
|
||||
``crewai_core.token_manager`` directly.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from crewai_core.token_manager import TokenManager as TokenManager
|
||||
|
||||
|
||||
__all__ = ["TokenManager"]
|
||||
67
lib/cli/src/crewai_cli/task_outputs.py
Normal file
67
lib/cli/src/crewai_cli/task_outputs.py
Normal file
@@ -0,0 +1,67 @@
|
||||
"""Lightweight SQLite reader for kickoff task outputs.
|
||||
|
||||
Only used by the ``crewai log-tasks-outputs`` CLI command. Depends solely on
|
||||
the standard library + *appdirs* so crewai-cli can read stored outputs without
|
||||
importing the full crewai framework.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import sqlite3
|
||||
from typing import Any
|
||||
|
||||
from crewai_cli.user_data import _db_storage_path
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def load_task_outputs(db_path: str | None = None) -> list[dict[str, Any]]:
|
||||
"""Return all rows from the kickoff task outputs database."""
|
||||
if db_path is None:
|
||||
db_path = str(Path(_db_storage_path()) / "latest_kickoff_task_outputs.db")
|
||||
|
||||
if not Path(db_path).exists():
|
||||
return []
|
||||
|
||||
try:
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
conn.row_factory = sqlite3.Row
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
SELECT task_id, expected_output, output, task_index,
|
||||
inputs, was_replayed, timestamp
|
||||
FROM latest_kickoff_task_outputs
|
||||
ORDER BY task_index
|
||||
""")
|
||||
rows = cursor.fetchall()
|
||||
except sqlite3.Error as e:
|
||||
logger.error("Failed to load task outputs: %s", e)
|
||||
return []
|
||||
|
||||
return [
|
||||
{
|
||||
"task_id": row["task_id"],
|
||||
"expected_output": row["expected_output"],
|
||||
"output": _safe_json_loads(row["output"]),
|
||||
"task_index": row["task_index"],
|
||||
"inputs": _safe_json_loads(row["inputs"]),
|
||||
"was_replayed": row["was_replayed"],
|
||||
"timestamp": row["timestamp"],
|
||||
}
|
||||
for row in rows
|
||||
]
|
||||
|
||||
|
||||
def _safe_json_loads(value: str | None) -> Any:
|
||||
"""Decode a JSON column tolerantly: NULL/blank/corrupt → None."""
|
||||
if not value:
|
||||
return None
|
||||
try:
|
||||
return json.loads(value)
|
||||
except (json.JSONDecodeError, TypeError) as e:
|
||||
logger.warning("Failed to decode JSON column: %s", e)
|
||||
return None
|
||||
@@ -774,7 +774,7 @@ def calculator(expression: str) -> str:
|
||||
```
|
||||
|
||||
### Built-in Tools (install with `uv add crewai-tools`)
|
||||
Web/Search: SerperDevTool, ScrapeWebsiteTool, WebsiteSearchTool, EXASearchTool, FirecrawlSearchTool
|
||||
Web/Search: SerperDevTool, ScrapeWebsiteTool, WebsiteSearchTool, ExaSearchTool, FirecrawlSearchTool
|
||||
Documents: FileReadTool, DirectoryReadTool, PDFSearchTool, DOCXSearchTool, CSVSearchTool, JSONSearchTool, XMLSearchTool, MDXSearchTool
|
||||
Code: CodeInterpreterTool, CodeDocsSearchTool, GithubSearchTool
|
||||
Media: DALL-E Tool, YoutubeChannelSearchTool, YoutubeVideoSearchTool
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user