mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-02-28 00:38:13 +00:00
Compare commits
6 Commits
release/1.
...
gl/ci/pr-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
156b9d3285 | ||
|
|
757a435ee3 | ||
|
|
8bfdb188f7 | ||
|
|
1bdb9496a3 | ||
|
|
979aa26c3d | ||
|
|
514c082882 |
37
.github/workflows/pr-size.yml
vendored
Normal file
37
.github/workflows/pr-size.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: PR Size Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
pr-size:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: codelytv/pr-size-labeler@v1
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
xs_label: "size/XS"
|
||||
xs_max_size: 25
|
||||
s_label: "size/S"
|
||||
s_max_size: 100
|
||||
m_label: "size/M"
|
||||
m_max_size: 250
|
||||
l_label: "size/L"
|
||||
l_max_size: 500
|
||||
xl_label: "size/XL"
|
||||
fail_if_xl: true
|
||||
message_if_xl: >
|
||||
This PR exceeds 500 lines changed and has been labeled `size/XL`.
|
||||
PRs of this size require release manager approval to merge.
|
||||
Please consider splitting into smaller PRs, or add a justification
|
||||
in the PR description for why this cannot be broken up.
|
||||
files_to_ignore: |
|
||||
uv.lock
|
||||
*.lock
|
||||
lib/crewai/src/crewai/cli/templates/**
|
||||
**/*.json
|
||||
**/test_durations/**
|
||||
**/cassettes/**
|
||||
38
.github/workflows/pr-title.yml
vendored
Normal file
38
.github/workflows/pr-title.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
name: PR Title Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
pr-title:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
types: |
|
||||
feat
|
||||
fix
|
||||
refactor
|
||||
perf
|
||||
test
|
||||
docs
|
||||
chore
|
||||
ci
|
||||
style
|
||||
revert
|
||||
requireScope: false
|
||||
subjectPattern: ^[a-z].+[^.]$
|
||||
subjectPatternError: >
|
||||
The PR title "{title}" does not follow conventional commit format.
|
||||
|
||||
Expected: <type>(<scope>): <lowercase description without trailing period>
|
||||
|
||||
Examples:
|
||||
feat(memory): add lancedb storage backend
|
||||
fix(agents): resolve deadlock in concurrent execution
|
||||
chore(deps): bump pydantic to 2.11.9
|
||||
|
||||
See RELEASE_PROCESS.md for the full commit message convention.
|
||||
@@ -4,6 +4,56 @@ description: "Product updates, improvements, and bug fixes for CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="Feb 27, 2026">
|
||||
## v1.10.1a1
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.10.1a1)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Implement asynchronous invocation support in step callback methods
|
||||
- Implement lazy loading for heavy dependencies in Memory module
|
||||
|
||||
### Documentation
|
||||
- Update changelog and version for v1.10.0
|
||||
|
||||
### Refactoring
|
||||
- Refactor step callback methods to support asynchronous invocation
|
||||
- Refactor to implement lazy loading for heavy dependencies in Memory module
|
||||
|
||||
### Bug Fixes
|
||||
- Fix branch for release notes
|
||||
|
||||
## Contributors
|
||||
|
||||
@greysonlalonde, @joaomdmoura
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Feb 27, 2026">
|
||||
## v1.10.1a1
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.10.1a1)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Refactoring
|
||||
- Refactor step callback methods to support asynchronous invocation
|
||||
- Implement lazy loading for heavy dependencies in Memory module
|
||||
|
||||
### Documentation
|
||||
- Update changelog and version for v1.10.0
|
||||
|
||||
### Bug Fixes
|
||||
- Make branch for release notes
|
||||
|
||||
## Contributors
|
||||
|
||||
@greysonlalonde, @joaomdmoura
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Feb 26, 2026">
|
||||
## v1.10.0
|
||||
|
||||
|
||||
@@ -4,6 +4,56 @@ description: "CrewAI의 제품 업데이트, 개선 사항 및 버그 수정"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="2026년 2월 27일">
|
||||
## v1.10.1a1
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.10.1a1)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- 단계 콜백 메서드에서 비동기 호출 지원 구현
|
||||
- 메모리 모듈의 무거운 의존성에 대한 지연 로딩 구현
|
||||
|
||||
### 문서
|
||||
- v1.10.0에 대한 변경 로그 및 버전 업데이트
|
||||
|
||||
### 리팩토링
|
||||
- 비동기 호출을 지원하기 위해 단계 콜백 메서드 리팩토링
|
||||
- 메모리 모듈의 무거운 의존성에 대한 지연 로딩을 구현하기 위해 리팩토링
|
||||
|
||||
### 버그 수정
|
||||
- 릴리스 노트의 분기 수정
|
||||
|
||||
## 기여자
|
||||
|
||||
@greysonlalonde, @joaomdmoura
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 2월 27일">
|
||||
## v1.10.1a1
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.10.1a1)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 리팩토링
|
||||
- 비동기 호출을 지원하기 위해 단계 콜백 메서드 리팩토링
|
||||
- 메모리 모듈의 무거운 의존성에 대해 지연 로딩 구현
|
||||
|
||||
### 문서화
|
||||
- v1.10.0에 대한 변경 로그 및 버전 업데이트
|
||||
|
||||
### 버그 수정
|
||||
- 릴리스 노트를 위한 브랜치 생성
|
||||
|
||||
## 기여자
|
||||
|
||||
@greysonlalonde, @joaomdmoura
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 2월 26일">
|
||||
## v1.10.0
|
||||
|
||||
|
||||
@@ -4,6 +4,56 @@ description: "Atualizações de produto, melhorias e correções do CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="27 fev 2026">
|
||||
## v1.10.1a1
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.10.1a1)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Funcionalidades
|
||||
- Implementar suporte a invocação assíncrona em métodos de callback de etapas
|
||||
- Implementar carregamento sob demanda para dependências pesadas no módulo de Memória
|
||||
|
||||
### Documentação
|
||||
- Atualizar changelog e versão para v1.10.0
|
||||
|
||||
### Refatoração
|
||||
- Refatorar métodos de callback de etapas para suportar invocação assíncrona
|
||||
- Refatorar para implementar carregamento sob demanda para dependências pesadas no módulo de Memória
|
||||
|
||||
### Correções de Bugs
|
||||
- Corrigir branch para notas de lançamento
|
||||
|
||||
## Contribuidores
|
||||
|
||||
@greysonlalonde, @joaomdmoura
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="27 fev 2026">
|
||||
## v1.10.1a1
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.10.1a1)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Refatoração
|
||||
- Refatorar métodos de callback de etapas para suportar invocação assíncrona
|
||||
- Implementar carregamento sob demanda para dependências pesadas no módulo de Memória
|
||||
|
||||
### Documentação
|
||||
- Atualizar changelog e versão para v1.10.0
|
||||
|
||||
### Correções de Bugs
|
||||
- Criar branch para notas de lançamento
|
||||
|
||||
## Contribuidores
|
||||
|
||||
@greysonlalonde, @joaomdmoura
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="26 fev 2026">
|
||||
## v1.10.0
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ dependencies = [
|
||||
"python-magic>=0.4.27",
|
||||
"aiocache~=0.12.3",
|
||||
"aiofiles~=24.1.0",
|
||||
"tinytag~=1.10.1a",
|
||||
"tinytag~=1.10.0",
|
||||
"av~=13.0.0",
|
||||
]
|
||||
|
||||
|
||||
@@ -152,4 +152,4 @@ __all__ = [
|
||||
"wrap_file_source",
|
||||
]
|
||||
|
||||
__version__ = "1.10.1a"
|
||||
__version__ = "1.10.1a1"
|
||||
|
||||
@@ -11,7 +11,7 @@ dependencies = [
|
||||
"pytube~=15.0.0",
|
||||
"requests~=2.32.5",
|
||||
"docker~=7.1.0",
|
||||
"crewai==1.10.1a",
|
||||
"crewai==1.10.1a1",
|
||||
"tiktoken~=0.8.0",
|
||||
"beautifulsoup4~=4.13.4",
|
||||
"python-docx~=1.2.0",
|
||||
|
||||
@@ -291,4 +291,4 @@ __all__ = [
|
||||
"ZapierActionTools",
|
||||
]
|
||||
|
||||
__version__ = "1.10.1a"
|
||||
__version__ = "1.10.1a1"
|
||||
|
||||
@@ -53,7 +53,7 @@ Repository = "https://github.com/crewAIInc/crewAI"
|
||||
|
||||
[project.optional-dependencies]
|
||||
tools = [
|
||||
"crewai-tools==1.10.1a",
|
||||
"crewai-tools==1.10.1a1",
|
||||
]
|
||||
embeddings = [
|
||||
"tiktoken~=0.8.0"
|
||||
|
||||
@@ -10,7 +10,6 @@ from crewai.flow.flow import Flow
|
||||
from crewai.knowledge.knowledge import Knowledge
|
||||
from crewai.llm import LLM
|
||||
from crewai.llms.base_llm import BaseLLM
|
||||
from crewai.memory.unified_memory import Memory
|
||||
from crewai.process import Process
|
||||
from crewai.task import Task
|
||||
from crewai.tasks.llm_guardrail import LLMGuardrail
|
||||
@@ -41,7 +40,7 @@ def _suppress_pydantic_deprecation_warnings() -> None:
|
||||
|
||||
_suppress_pydantic_deprecation_warnings()
|
||||
|
||||
__version__ = "1.10.1a"
|
||||
__version__ = "1.10.1a1"
|
||||
_telemetry_submitted = False
|
||||
|
||||
|
||||
@@ -72,6 +71,25 @@ def _track_install_async() -> None:
|
||||
|
||||
|
||||
_track_install_async()
|
||||
|
||||
_LAZY_IMPORTS: dict[str, tuple[str, str]] = {
|
||||
"Memory": ("crewai.memory.unified_memory", "Memory"),
|
||||
}
|
||||
|
||||
|
||||
def __getattr__(name: str) -> Any:
|
||||
"""Lazily import heavy modules (e.g. Memory → lancedb) on first access."""
|
||||
if name in _LAZY_IMPORTS:
|
||||
module_path, attr = _LAZY_IMPORTS[name]
|
||||
import importlib
|
||||
|
||||
mod = importlib.import_module(module_path)
|
||||
val = getattr(mod, attr)
|
||||
globals()[name] = val
|
||||
return val
|
||||
raise AttributeError(f"module 'crewai' has no attribute {name!r}")
|
||||
|
||||
|
||||
__all__ = [
|
||||
"LLM",
|
||||
"Agent",
|
||||
|
||||
@@ -1259,7 +1259,7 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
|
||||
formatted_answer, tool_result
|
||||
)
|
||||
|
||||
self._invoke_step_callback(formatted_answer) # type: ignore[arg-type]
|
||||
await self._ainvoke_step_callback(formatted_answer) # type: ignore[arg-type]
|
||||
self._append_message(formatted_answer.text) # type: ignore[union-attr]
|
||||
|
||||
except OutputParserError as e:
|
||||
@@ -1374,7 +1374,7 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
|
||||
output=answer,
|
||||
text=answer,
|
||||
)
|
||||
self._invoke_step_callback(formatted_answer)
|
||||
await self._ainvoke_step_callback(formatted_answer)
|
||||
self._append_message(answer) # Save final answer to messages
|
||||
self._show_logs(formatted_answer)
|
||||
return formatted_answer
|
||||
@@ -1386,7 +1386,7 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
|
||||
output=answer,
|
||||
text=output_json,
|
||||
)
|
||||
self._invoke_step_callback(formatted_answer)
|
||||
await self._ainvoke_step_callback(formatted_answer)
|
||||
self._append_message(output_json)
|
||||
self._show_logs(formatted_answer)
|
||||
return formatted_answer
|
||||
@@ -1397,7 +1397,7 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
|
||||
output=str(answer),
|
||||
text=str(answer),
|
||||
)
|
||||
self._invoke_step_callback(formatted_answer)
|
||||
await self._ainvoke_step_callback(formatted_answer)
|
||||
self._append_message(str(answer)) # Save final answer to messages
|
||||
self._show_logs(formatted_answer)
|
||||
return formatted_answer
|
||||
@@ -1491,7 +1491,7 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
|
||||
def _invoke_step_callback(
|
||||
self, formatted_answer: AgentAction | AgentFinish
|
||||
) -> None:
|
||||
"""Invoke step callback.
|
||||
"""Invoke step callback (sync context).
|
||||
|
||||
Args:
|
||||
formatted_answer: Current agent response.
|
||||
@@ -1501,6 +1501,19 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
|
||||
if inspect.iscoroutine(cb_result):
|
||||
asyncio.run(cb_result)
|
||||
|
||||
async def _ainvoke_step_callback(
|
||||
self, formatted_answer: AgentAction | AgentFinish
|
||||
) -> None:
|
||||
"""Invoke step callback (async context).
|
||||
|
||||
Args:
|
||||
formatted_answer: Current agent response.
|
||||
"""
|
||||
if self.step_callback:
|
||||
cb_result = self.step_callback(formatted_answer)
|
||||
if inspect.iscoroutine(cb_result):
|
||||
await cb_result
|
||||
|
||||
def _append_message(
|
||||
self, text: str, role: Literal["user", "assistant", "system"] = "assistant"
|
||||
) -> None:
|
||||
|
||||
@@ -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.10.1a"
|
||||
"crewai[tools]==1.10.1a1"
|
||||
]
|
||||
|
||||
[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.10.1a"
|
||||
"crewai[tools]==1.10.1a1"
|
||||
]
|
||||
|
||||
[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.10.1a"
|
||||
"crewai[tools]==1.10.1a1"
|
||||
]
|
||||
|
||||
[tool.crewai]
|
||||
|
||||
@@ -16,7 +16,7 @@ from collections.abc import (
|
||||
Sequence,
|
||||
ValuesView,
|
||||
)
|
||||
from concurrent.futures import Future
|
||||
from concurrent.futures import Future, ThreadPoolExecutor
|
||||
import copy
|
||||
import enum
|
||||
import inspect
|
||||
@@ -1739,7 +1739,12 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
||||
async def _run_flow() -> Any:
|
||||
return await self.kickoff_async(inputs, input_files)
|
||||
|
||||
return asyncio.run(_run_flow())
|
||||
try:
|
||||
asyncio.get_running_loop()
|
||||
with ThreadPoolExecutor(max_workers=1) as pool:
|
||||
return pool.submit(asyncio.run, _run_flow()).result()
|
||||
except RuntimeError:
|
||||
return asyncio.run(_run_flow())
|
||||
|
||||
async def kickoff_async(
|
||||
self,
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
"""Memory module: unified Memory with LLM analysis and pluggable storage."""
|
||||
"""Memory module: unified Memory with LLM analysis and pluggable storage.
|
||||
|
||||
Heavy dependencies are lazily imported so that
|
||||
``import crewai`` does not initialise at runtime — critical for
|
||||
Celery pre-fork and similar deployment patterns.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from crewai.memory.encoding_flow import EncodingFlow
|
||||
from crewai.memory.memory_scope import MemoryScope, MemorySlice
|
||||
from crewai.memory.types import (
|
||||
MemoryMatch,
|
||||
@@ -10,7 +18,24 @@ from crewai.memory.types import (
|
||||
embed_text,
|
||||
embed_texts,
|
||||
)
|
||||
from crewai.memory.unified_memory import Memory
|
||||
|
||||
_LAZY_IMPORTS: dict[str, tuple[str, str]] = {
|
||||
"Memory": ("crewai.memory.unified_memory", "Memory"),
|
||||
"EncodingFlow": ("crewai.memory.encoding_flow", "EncodingFlow"),
|
||||
}
|
||||
|
||||
|
||||
def __getattr__(name: str) -> Any:
|
||||
"""Lazily import Memory / EncodingFlow to avoid pulling in lancedb at import time."""
|
||||
if name in _LAZY_IMPORTS:
|
||||
import importlib
|
||||
|
||||
module_path, attr = _LAZY_IMPORTS[name]
|
||||
mod = importlib.import_module(module_path)
|
||||
val = getattr(mod, attr)
|
||||
globals()[name] = val
|
||||
return val
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
||||
@@ -21,7 +21,6 @@ from crewai.llms.base_llm import BaseLLM
|
||||
from crewai.memory.analyze import extract_memories_from_content
|
||||
from crewai.memory.recall_flow import RecallFlow
|
||||
from crewai.memory.storage.backend import StorageBackend
|
||||
from crewai.memory.storage.lancedb_storage import LanceDBStorage
|
||||
from crewai.memory.types import (
|
||||
MemoryConfig,
|
||||
MemoryMatch,
|
||||
@@ -148,12 +147,10 @@ class Memory:
|
||||
else None
|
||||
)
|
||||
|
||||
# Storage is initialized eagerly (local, no API key needed).
|
||||
self._storage: StorageBackend
|
||||
if storage == "lancedb":
|
||||
self._storage = LanceDBStorage()
|
||||
elif isinstance(storage, str):
|
||||
self._storage = LanceDBStorage(path=storage)
|
||||
if isinstance(storage, str):
|
||||
from crewai.memory.storage.lancedb_storage import LanceDBStorage
|
||||
|
||||
self._storage = LanceDBStorage() if storage == "lancedb" else LanceDBStorage(path=storage)
|
||||
else:
|
||||
self._storage = storage
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"""CrewAI development tools."""
|
||||
|
||||
__version__ = "1.10.1a"
|
||||
__version__ = "1.10.1a1"
|
||||
|
||||
@@ -200,7 +200,7 @@ def add_docs_version(docs_json_path: Path, version: str) -> bool:
|
||||
|
||||
Args:
|
||||
docs_json_path: Path to docs/docs.json.
|
||||
version: Version string (e.g., "1.10.1a").
|
||||
version: Version string (e.g., "1.10.1b1").
|
||||
|
||||
Returns:
|
||||
True if docs.json was updated, False otherwise.
|
||||
|
||||
@@ -142,6 +142,22 @@ python_files = "test_*.py"
|
||||
python_classes = "Test*"
|
||||
python_functions = "test_*"
|
||||
|
||||
[tool.commitizen]
|
||||
name = "cz_conventional_commits"
|
||||
version_provider = "scm"
|
||||
tag_format = "$version"
|
||||
allowed_prefixes = ["Merge", "Revert"]
|
||||
changelog_incremental = true
|
||||
update_changelog_on_bump = false
|
||||
|
||||
[tool.commitizen.customize]
|
||||
schema = "<type>(<scope>): <description>"
|
||||
schema_pattern = "^(feat|fix|refactor|perf|test|docs|chore|ci|style|revert)(\\(.+\\))?!?: .{1,72}"
|
||||
bump_pattern = "^(feat|fix|perf|refactor|revert)"
|
||||
bump_map = { feat = "MINOR", fix = "PATCH", perf = "PATCH", refactor = "PATCH", revert = "PATCH" }
|
||||
info = "Commits must follow Conventional Commits 1.0.0. See RELEASE_PROCESS.md for details."
|
||||
|
||||
|
||||
[tool.uv]
|
||||
|
||||
# composio-core pins rich<14 but textual requires rich>=14.
|
||||
|
||||
Reference in New Issue
Block a user