mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-18 15:38:10 +00:00
Compare commits
2 Commits
1.12.2
...
docs/file-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8ba5b823a | ||
|
|
5a850a708b |
@@ -4,29 +4,6 @@ description: "تحديثات المنتج والتحسينات وإصلاحات
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="25 مارس 2026">
|
||||
## v1.12.2
|
||||
|
||||
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.12.2)
|
||||
|
||||
## ما الذي تغير
|
||||
|
||||
### الميزات
|
||||
- إضافة مرحلة إصدار المؤسسات إلى إصدار أدوات المطورين
|
||||
|
||||
### إصلاحات الأخطاء
|
||||
- الحفاظ على قيمة إرجاع الطريقة كإخراج تدفق لـ @human_feedback مع emit
|
||||
|
||||
### الوثائق
|
||||
- تحديث سجل التغييرات والإصدار لـ v1.12.1
|
||||
- مراجعة سياسة الأمان وتعليمات الإبلاغ
|
||||
|
||||
## المساهمون
|
||||
|
||||
@alex-clawd, @greysonlalonde, @joaomdmoura, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="25 مارس 2026">
|
||||
## v1.12.1
|
||||
|
||||
|
||||
1863
docs/docs.json
1863
docs/docs.json
File diff suppressed because it is too large
Load Diff
@@ -4,29 +4,6 @@ description: "Product updates, improvements, and bug fixes for CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="Mar 25, 2026">
|
||||
## v1.12.2
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.12.2)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Add enterprise release phase to devtools release
|
||||
|
||||
### Bug Fixes
|
||||
- Preserve method return value as flow output for @human_feedback with emit
|
||||
|
||||
### Documentation
|
||||
- Update changelog and version for v1.12.1
|
||||
- Revise security policy and reporting instructions
|
||||
|
||||
## Contributors
|
||||
|
||||
@alex-clawd, @greysonlalonde, @joaomdmoura, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Mar 25, 2026">
|
||||
## v1.12.1
|
||||
|
||||
|
||||
@@ -134,6 +134,29 @@ result = flow.kickoff(
|
||||
)
|
||||
```
|
||||
|
||||
You can also define file types directly in your flow state for structured file handling:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai_files import ImageFile, PDFFile
|
||||
|
||||
class DocumentState(BaseModel):
|
||||
document: PDFFile
|
||||
cover_image: ImageFile
|
||||
title: str = ""
|
||||
|
||||
class DocumentFlow(Flow[DocumentState]):
|
||||
@start()
|
||||
def process(self):
|
||||
content = self.state.document.read()
|
||||
return {"processed": True}
|
||||
```
|
||||
|
||||
<Note type="info" title="CrewAI Platform Integration">
|
||||
When deploying flows to the CrewAI Platform (AMP), file fields in your state automatically render as file upload dropzones in the UI. For API usage, you can pass URL strings directly and Pydantic coerces them to file objects automatically. See [Flows - File Inputs](/en/concepts/flows#file-inputs) for details.
|
||||
</Note>
|
||||
|
||||
### With Standalone Agents
|
||||
|
||||
Pass files directly to agent kickoff:
|
||||
|
||||
@@ -341,6 +341,69 @@ flow.kickoff()
|
||||
|
||||
By providing both unstructured and structured state management options, CrewAI Flows empowers developers to build AI workflows that are both flexible and robust, catering to a wide range of application requirements.
|
||||
|
||||
## File Inputs
|
||||
|
||||
Flows support file inputs through the `crewai-files` package, enabling you to build workflows that process images, PDFs, and other file types. When you use file types like `ImageFile` or `PDFFile` in your flow state, they integrate seamlessly with both local development and the CrewAI Platform.
|
||||
|
||||
<Note type="info" title="Optional Dependency">
|
||||
File support requires the optional `crewai-files` package. Install it with:
|
||||
|
||||
```bash
|
||||
uv add 'crewai[file-processing]'
|
||||
```
|
||||
</Note>
|
||||
|
||||
### Using File Types in Flow State
|
||||
|
||||
You can include file types directly in your structured flow state:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel
|
||||
from crewai.flow.flow import Flow, start
|
||||
from crewai_files import ImageFile, PDFFile
|
||||
|
||||
class DocumentProcessingState(BaseModel):
|
||||
document: PDFFile # Renders as file upload in CrewAI Platform
|
||||
cover_image: ImageFile # Renders as image upload
|
||||
title: str = "" # Renders as text input
|
||||
|
||||
class DocumentFlow(Flow[DocumentProcessingState]):
|
||||
@start()
|
||||
def process_document(self):
|
||||
# Access the file - works with URLs, paths, or uploaded files
|
||||
content = self.state.document.read()
|
||||
# Or pass to an agent with VisionTool, etc.
|
||||
return {"processed": True}
|
||||
```
|
||||
|
||||
### CrewAI Platform Integration
|
||||
|
||||
When you deploy a flow to the CrewAI Platform (AMP), file fields in your state automatically render as file upload dropzones in the UI. This makes it easy to build user-facing applications that accept file uploads without any additional frontend work.
|
||||
|
||||
| State Field Type | Platform UI Rendering |
|
||||
|:-----------------|:----------------------|
|
||||
| `ImageFile` | Image upload dropzone |
|
||||
| `PDFFile` | PDF upload dropzone |
|
||||
| `AudioFile` | Audio upload dropzone |
|
||||
| `VideoFile` | Video upload dropzone |
|
||||
| `TextFile` | Text file upload dropzone |
|
||||
| `str`, `int`, etc. | Standard form inputs |
|
||||
|
||||
### API Usage
|
||||
|
||||
When calling your flow via API, you can pass URL strings directly for file fields. Pydantic automatically coerces URLs into the appropriate file type:
|
||||
|
||||
```python
|
||||
# API request body - URLs are automatically converted to file objects
|
||||
{
|
||||
"document": "https://example.com/report.pdf",
|
||||
"cover_image": "https://example.com/cover.png",
|
||||
"title": "Q4 Report"
|
||||
}
|
||||
```
|
||||
|
||||
For more details on file types, sources, and provider support, see the [Files documentation](/en/concepts/files).
|
||||
|
||||
## Flow Persistence
|
||||
|
||||
The @persist decorator enables automatic state persistence in CrewAI Flows, allowing you to maintain flow state across restarts or different workflow executions. This decorator can be applied at either the class level or method level, providing flexibility in how you manage state persistence.
|
||||
|
||||
@@ -4,29 +4,6 @@ description: "CrewAI의 제품 업데이트, 개선 사항 및 버그 수정"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="2026년 3월 25일">
|
||||
## v1.12.2
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.12.2)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- devtools 릴리스에 기업 릴리스 단계 추가
|
||||
|
||||
### 버그 수정
|
||||
- @human_feedback과 함께 emit을 사용할 때 메서드 반환 값을 흐름 출력으로 유지
|
||||
|
||||
### 문서
|
||||
- v1.12.1에 대한 변경 로그 및 버전 업데이트
|
||||
- 보안 정책 및 보고 지침 수정
|
||||
|
||||
## 기여자
|
||||
|
||||
@alex-clawd, @greysonlalonde, @joaomdmoura, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 3월 25일">
|
||||
## v1.12.1
|
||||
|
||||
|
||||
@@ -4,29 +4,6 @@ description: "Atualizações de produto, melhorias e correções do CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="25 mar 2026">
|
||||
## v1.12.2
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.12.2)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Recursos
|
||||
- Adicionar fase de lançamento empresarial ao lançamento do devtools
|
||||
|
||||
### Correções de Bugs
|
||||
- Preservar o valor de retorno do método como saída de fluxo para @human_feedback com emit
|
||||
|
||||
### Documentação
|
||||
- Atualizar changelog e versão para v1.12.1
|
||||
- Revisar política de segurança e instruções de relatório
|
||||
|
||||
## Contributors
|
||||
|
||||
@alex-clawd, @greysonlalonde, @joaomdmoura, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="25 mar 2026">
|
||||
## v1.12.1
|
||||
|
||||
|
||||
@@ -152,4 +152,4 @@ __all__ = [
|
||||
"wrap_file_source",
|
||||
]
|
||||
|
||||
__version__ = "1.12.2"
|
||||
__version__ = "1.12.1"
|
||||
|
||||
@@ -11,7 +11,7 @@ dependencies = [
|
||||
"pytube~=15.0.0",
|
||||
"requests~=2.32.5",
|
||||
"docker~=7.1.0",
|
||||
"crewai==1.12.2",
|
||||
"crewai==1.12.1",
|
||||
"tiktoken~=0.8.0",
|
||||
"beautifulsoup4~=4.13.4",
|
||||
"python-docx~=1.2.0",
|
||||
|
||||
@@ -309,4 +309,4 @@ __all__ = [
|
||||
"ZapierActionTools",
|
||||
]
|
||||
|
||||
__version__ = "1.12.2"
|
||||
__version__ = "1.12.1"
|
||||
|
||||
@@ -54,7 +54,7 @@ Repository = "https://github.com/crewAIInc/crewAI"
|
||||
|
||||
[project.optional-dependencies]
|
||||
tools = [
|
||||
"crewai-tools==1.12.2",
|
||||
"crewai-tools==1.12.1",
|
||||
]
|
||||
embeddings = [
|
||||
"tiktoken~=0.8.0"
|
||||
|
||||
@@ -42,7 +42,7 @@ def _suppress_pydantic_deprecation_warnings() -> None:
|
||||
|
||||
_suppress_pydantic_deprecation_warnings()
|
||||
|
||||
__version__ = "1.12.2"
|
||||
__version__ = "1.12.1"
|
||||
_telemetry_submitted = False
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "{{name}} using crewAI"
|
||||
authors = [{ name = "Your Name", email = "you@example.com" }]
|
||||
requires-python = ">=3.10,<3.14"
|
||||
dependencies = [
|
||||
"crewai[tools]==1.12.2"
|
||||
"crewai[tools]==1.12.1"
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "{{name}} using crewAI"
|
||||
authors = [{ name = "Your Name", email = "you@example.com" }]
|
||||
requires-python = ">=3.10,<3.14"
|
||||
dependencies = [
|
||||
"crewai[tools]==1.12.2"
|
||||
"crewai[tools]==1.12.1"
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -5,7 +5,7 @@ description = "Power up your crews with {{folder_name}}"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10,<3.14"
|
||||
dependencies = [
|
||||
"crewai[tools]==1.12.2"
|
||||
"crewai[tools]==1.12.1"
|
||||
]
|
||||
|
||||
[tool.crewai]
|
||||
|
||||
@@ -883,9 +883,7 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
self.human_feedback_history: list[HumanFeedbackResult] = []
|
||||
self.last_human_feedback: HumanFeedbackResult | None = None
|
||||
self._pending_feedback_context: PendingFeedbackContext | None = None
|
||||
# Per-method stash for real @human_feedback output (keyed by method name)
|
||||
# Used to decouple routing outcome from method return value when emit is set
|
||||
self._human_feedback_method_outputs: dict[str, Any] = {}
|
||||
self._human_feedback_method_output: Any = None # Stashed real output from @human_feedback with emit
|
||||
self.suppress_flow_events: bool = suppress_flow_events
|
||||
|
||||
# User input history (for self.ask())
|
||||
@@ -2297,12 +2295,10 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
# For @human_feedback methods with emit, the result is the collapsed outcome
|
||||
# (e.g., "approved") used for routing. But we want the actual method output
|
||||
# to be the stored result (for final flow output). Replace the last entry
|
||||
# if a stashed output exists. Dict-based stash is concurrency-safe and
|
||||
# handles None return values (presence in dict = stashed, not value).
|
||||
if method_name in self._human_feedback_method_outputs:
|
||||
self._method_outputs[-1] = self._human_feedback_method_outputs.pop(
|
||||
method_name
|
||||
)
|
||||
# if a stashed output exists.
|
||||
if self._human_feedback_method_output is not None:
|
||||
self._method_outputs[-1] = self._human_feedback_method_output
|
||||
self._human_feedback_method_output = None
|
||||
|
||||
self._method_execution_counts[method_name] = (
|
||||
self._method_execution_counts.get(method_name, 0) + 1
|
||||
|
||||
@@ -594,9 +594,8 @@ def human_feedback(
|
||||
# Stash the real method output for final flow result when emit is set
|
||||
# (result is the collapsed outcome string for routing, but we want to
|
||||
# preserve the actual method output as the flow's final result)
|
||||
# Uses per-method dict for concurrency safety and to handle None returns
|
||||
if emit:
|
||||
self._human_feedback_method_outputs[func.__name__] = method_output
|
||||
self._human_feedback_method_output = method_output
|
||||
|
||||
return result
|
||||
|
||||
@@ -625,9 +624,8 @@ def human_feedback(
|
||||
# Stash the real method output for final flow result when emit is set
|
||||
# (result is the collapsed outcome string for routing, but we want to
|
||||
# preserve the actual method output as the flow's final result)
|
||||
# Uses per-method dict for concurrency safety and to handle None returns
|
||||
if emit:
|
||||
self._human_feedback_method_outputs[func.__name__] = method_output
|
||||
self._human_feedback_method_output = method_output
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -726,31 +726,3 @@ class TestHumanFeedbackFinalOutputPreservation:
|
||||
# _method_outputs should contain the real output
|
||||
assert len(flow._method_outputs) == 1
|
||||
assert flow._method_outputs[0] == {"data": "real output"}
|
||||
|
||||
@patch("builtins.input", return_value="looks good")
|
||||
@patch("builtins.print")
|
||||
def test_none_return_value_is_preserved(self, mock_print, mock_input):
|
||||
"""A method returning None should preserve None as flow output, not the outcome string."""
|
||||
|
||||
class NoneReturnFlow(Flow):
|
||||
@start()
|
||||
@human_feedback(
|
||||
message="Review:",
|
||||
emit=["approved", "rejected"],
|
||||
llm="gpt-4o-mini",
|
||||
)
|
||||
def process(self):
|
||||
# Method does work but returns None (implicit)
|
||||
pass
|
||||
|
||||
flow = NoneReturnFlow()
|
||||
|
||||
with (
|
||||
patch.object(flow, "_request_human_feedback", return_value=""),
|
||||
patch.object(flow, "_collapse_to_outcome", return_value="approved"),
|
||||
):
|
||||
result = flow.kickoff()
|
||||
|
||||
# Final output should be None (the method's real return), not "approved"
|
||||
assert result is None, f"Expected None, got {result!r}"
|
||||
assert flow.last_human_feedback.outcome == "approved"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"""CrewAI development tools."""
|
||||
|
||||
__version__ = "1.12.2"
|
||||
__version__ = "1.12.1"
|
||||
|
||||
Reference in New Issue
Block a user