agentflowkit 0.1.0__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. agentflowkit-0.5.0/.coverage +0 -0
  2. agentflowkit-0.5.0/.github/ISSUE_TEMPLATE/bug_report.md +43 -0
  3. agentflowkit-0.5.0/.github/ISSUE_TEMPLATE/feature_request.md +29 -0
  4. agentflowkit-0.5.0/.github/workflows/ci.yml +81 -0
  5. agentflowkit-0.5.0/.github/workflows/docs.yml +32 -0
  6. agentflowkit-0.5.0/.github/workflows/publish.yml +33 -0
  7. agentflowkit-0.5.0/.gitignore +21 -0
  8. agentflowkit-0.5.0/AUDIT_REPORT.md +137 -0
  9. agentflowkit-0.5.0/CHANGELOG.md +111 -0
  10. agentflowkit-0.5.0/CMakeLists.txt +30 -0
  11. agentflowkit-0.5.0/CONTRIBUTING.md +99 -0
  12. agentflowkit-0.5.0/PASS2_RESOLUTION_REPORT.md +261 -0
  13. agentflowkit-0.5.0/PKG-INFO +430 -0
  14. agentflowkit-0.5.0/README.md +388 -0
  15. agentflowkit-0.5.0/benchmarks/parallel_speedup.py +71 -0
  16. agentflowkit-0.5.0/docs/getting-started.md +83 -0
  17. agentflowkit-0.5.0/docs/guides/cost-streaming.md +48 -0
  18. agentflowkit-0.5.0/docs/guides/memory.md +195 -0
  19. agentflowkit-0.5.0/docs/guides/observability.md +52 -0
  20. agentflowkit-0.5.0/docs/guides/tools.md +58 -0
  21. agentflowkit-0.5.0/docs/index.md +42 -0
  22. agentflowkit-0.5.0/docs/reference.md +49 -0
  23. {agentflowkit-0.1.0 → agentflowkit-0.5.0}/examples/code_reviewer.py +1 -2
  24. agentflowkit-0.5.0/examples/cpp_build_pipeline.py +293 -0
  25. agentflowkit-0.5.0/examples/drone_telemetry_agent.py +168 -0
  26. agentflowkit-0.5.0/examples/market_analysis_crew.py +258 -0
  27. agentflowkit-0.5.0/examples/memory_chat_agents.py +172 -0
  28. agentflowkit-0.5.0/examples/notebooks/parallel_execution_demo.ipynb +292 -0
  29. agentflowkit-0.5.0/examples/notebooks/quickstart.ipynb +269 -0
  30. {agentflowkit-0.1.0 → agentflowkit-0.5.0}/examples/research_crew.py +2 -3
  31. agentflowkit-0.5.0/examples/research_react_agent.py +146 -0
  32. agentflowkit-0.5.0/examples/robotics_mqtt_agent.py +114 -0
  33. agentflowkit-0.5.0/examples/streaming_and_cost.py +52 -0
  34. agentflowkit-0.5.0/examples/tool_agent.py +66 -0
  35. agentflowkit-0.5.0/mkdocs.yml +66 -0
  36. agentflowkit-0.5.0/pyproject.toml +85 -0
  37. agentflowkit-0.5.0/src/agentflow/__init__.py +95 -0
  38. agentflowkit-0.5.0/src/agentflow/agent.py +536 -0
  39. agentflowkit-0.5.0/src/agentflow/cache.py +143 -0
  40. agentflowkit-0.5.0/src/agentflow/cpp_core/bindings.cpp +36 -0
  41. agentflowkit-0.5.0/src/agentflow/cpp_core/dag_engine.cpp +105 -0
  42. agentflowkit-0.5.0/src/agentflow/cpp_core/dag_engine.h +22 -0
  43. agentflowkit-0.5.0/src/agentflow/distillation.py +160 -0
  44. agentflowkit-0.5.0/src/agentflow/events.py +254 -0
  45. agentflowkit-0.5.0/src/agentflow/exceptions.py +45 -0
  46. agentflowkit-0.5.0/src/agentflow/hitl.py +155 -0
  47. agentflowkit-0.5.0/src/agentflow/llm.py +248 -0
  48. agentflowkit-0.5.0/src/agentflow/logging.py +131 -0
  49. agentflowkit-0.5.0/src/agentflow/memory.py +478 -0
  50. agentflowkit-0.5.0/src/agentflow/observability.py +91 -0
  51. agentflowkit-0.5.0/src/agentflow/pipeline.py +729 -0
  52. agentflowkit-0.5.0/src/agentflow/pricing.py +57 -0
  53. agentflowkit-0.5.0/src/agentflow/py.typed +0 -0
  54. agentflowkit-0.5.0/src/agentflow/rate_limiter.py +86 -0
  55. agentflowkit-0.5.0/src/agentflow/sandbox.py +557 -0
  56. agentflowkit-0.5.0/src/agentflow/swarm.py +262 -0
  57. agentflowkit-0.5.0/src/agentflow/swarm_routing.py +321 -0
  58. agentflowkit-0.5.0/src/agentflow/tools.py +154 -0
  59. agentflowkit-0.5.0/src/agentflow/triggers.py +127 -0
  60. agentflowkit-0.5.0/src/agentflow/types.py +68 -0
  61. {agentflowkit-0.1.0 → agentflowkit-0.5.0}/tests/test_agent.py +1 -1
  62. agentflowkit-0.5.0/tests/test_cache.py +140 -0
  63. agentflowkit-0.5.0/tests/test_conditional.py +124 -0
  64. agentflowkit-0.5.0/tests/test_hitl.py +679 -0
  65. {agentflowkit-0.1.0 → agentflowkit-0.5.0}/tests/test_llm.py +0 -2
  66. agentflowkit-0.5.0/tests/test_logging.py +72 -0
  67. agentflowkit-0.5.0/tests/test_long_term_memory.py +440 -0
  68. agentflowkit-0.5.0/tests/test_memory.py +264 -0
  69. agentflowkit-0.5.0/tests/test_observability.py +99 -0
  70. agentflowkit-0.5.0/tests/test_parallel.py +242 -0
  71. {agentflowkit-0.1.0 → agentflowkit-0.5.0}/tests/test_pipeline.py +3 -5
  72. agentflowkit-0.5.0/tests/test_pricing.py +36 -0
  73. agentflowkit-0.5.0/tests/test_rate_limiter.py +57 -0
  74. agentflowkit-0.5.0/tests/test_retry.py +46 -0
  75. agentflowkit-0.5.0/tests/test_sandbox.py +466 -0
  76. agentflowkit-0.5.0/tests/test_streaming.py +54 -0
  77. agentflowkit-0.5.0/tests/test_swarm.py +419 -0
  78. agentflowkit-0.5.0/tests/test_swarm_routing.py +525 -0
  79. agentflowkit-0.5.0/tests/test_tools.py +231 -0
  80. agentflowkit-0.5.0/tests/test_triggers.py +386 -0
  81. agentflowkit-0.5.0/uv.lock +4179 -0
  82. agentflowkit-0.1.0/.gitignore +0 -11
  83. agentflowkit-0.1.0/PKG-INFO +0 -177
  84. agentflowkit-0.1.0/README.md +0 -149
  85. agentflowkit-0.1.0/pyproject.toml +0 -46
  86. agentflowkit-0.1.0/src/agentflow/__init__.py +0 -25
  87. agentflowkit-0.1.0/src/agentflow/agent.py +0 -97
  88. agentflowkit-0.1.0/src/agentflow/events.py +0 -32
  89. agentflowkit-0.1.0/src/agentflow/exceptions.py +0 -21
  90. agentflowkit-0.1.0/src/agentflow/llm.py +0 -96
  91. agentflowkit-0.1.0/src/agentflow/pipeline.py +0 -170
  92. agentflowkit-0.1.0/src/agentflow/types.py +0 -40
  93. agentflowkit-0.1.0/tmpclaude-0006-cwd +0 -1
  94. agentflowkit-0.1.0/tmpclaude-07af-cwd +0 -1
  95. agentflowkit-0.1.0/tmpclaude-153f-cwd +0 -1
  96. agentflowkit-0.1.0/tmpclaude-186c-cwd +0 -1
  97. agentflowkit-0.1.0/tmpclaude-1ebb-cwd +0 -1
  98. agentflowkit-0.1.0/tmpclaude-2838-cwd +0 -1
  99. agentflowkit-0.1.0/tmpclaude-2ebe-cwd +0 -1
  100. agentflowkit-0.1.0/tmpclaude-6962-cwd +0 -1
  101. agentflowkit-0.1.0/tmpclaude-6b68-cwd +0 -1
  102. agentflowkit-0.1.0/tmpclaude-8083-cwd +0 -1
  103. agentflowkit-0.1.0/tmpclaude-80d4-cwd +0 -1
  104. agentflowkit-0.1.0/tmpclaude-8eb0-cwd +0 -1
  105. agentflowkit-0.1.0/tmpclaude-94d9-cwd +0 -1
  106. agentflowkit-0.1.0/tmpclaude-a787-cwd +0 -1
  107. agentflowkit-0.1.0/tmpclaude-aea4-cwd +0 -1
  108. agentflowkit-0.1.0/tmpclaude-ba42-cwd +0 -1
  109. agentflowkit-0.1.0/tmpclaude-c025-cwd +0 -1
  110. agentflowkit-0.1.0/tmpclaude-c7b8-cwd +0 -1
  111. agentflowkit-0.1.0/tmpclaude-de78-cwd +0 -1
  112. agentflowkit-0.1.0/tmpclaude-de86-cwd +0 -1
  113. agentflowkit-0.1.0/tmpclaude-e628-cwd +0 -1
  114. agentflowkit-0.1.0/tmpclaude-e792-cwd +0 -1
  115. agentflowkit-0.1.0/tmpclaude-f142-cwd +0 -1
  116. agentflowkit-0.1.0/tmpclaude-f2e4-cwd +0 -1
  117. agentflowkit-0.1.0/tmpclaude-f501-cwd +0 -1
  118. agentflowkit-0.1.0/tmpclaude-fd1d-cwd +0 -1
  119. {agentflowkit-0.1.0 → agentflowkit-0.5.0}/.gitattributes +0 -0
  120. {agentflowkit-0.1.0 → agentflowkit-0.5.0}/LICENSE +0 -0
Binary file
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: Bug Report
3
+ about: Report a reproducible bug in agentflowkit
4
+ title: "[Bug] "
5
+ labels: bug
6
+ assignees: ""
7
+ ---
8
+
9
+ ## Description
10
+
11
+ A clear, concise description of the bug.
12
+
13
+ ## Reproduction Steps
14
+
15
+ ```python
16
+ # Minimal reproducible example
17
+ from agentflow import Agent, LLM, Pipeline
18
+
19
+ @Agent(name="example", role="Example")
20
+ async def example(task: str, context: dict) -> str:
21
+ return task
22
+
23
+ # Code that triggers the bug
24
+ ```
25
+
26
+ ## Expected Behavior
27
+
28
+ What you expected to happen.
29
+
30
+ ## Actual Behavior
31
+
32
+ What actually happened (include full traceback if applicable).
33
+
34
+ ## Environment
35
+
36
+ - `agentflowkit` version: <!-- e.g. 0.2.0 -->
37
+ - Python version: <!-- e.g. 3.11.5 -->
38
+ - OS: <!-- e.g. Ubuntu 22.04 / macOS 14 / Windows 11 -->
39
+ - LLM provider: <!-- e.g. OpenAI, Groq, Ollama -->
40
+
41
+ ## Additional Context
42
+
43
+ Any other context, screenshots, or logs that may help diagnose the issue.
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest a new feature or improvement
4
+ title: "[Feature] "
5
+ labels: enhancement
6
+ assignees: ""
7
+ ---
8
+
9
+ ## Problem Statement
10
+
11
+ What problem does this feature solve? Who is affected?
12
+
13
+ ## Proposed Solution
14
+
15
+ A clear description of what you want to happen.
16
+
17
+ ```python
18
+ # Ideally, show what the API would look like
19
+ pipe = Pipeline(llm=llm)
20
+ pipe.add(agent, new_feature_param=...)
21
+ ```
22
+
23
+ ## Alternatives Considered
24
+
25
+ Other approaches you considered and why you prefer this one.
26
+
27
+ ## Additional Context
28
+
29
+ Links to related issues, prior art in other frameworks (LangChain, CrewAI, etc.), or references.
@@ -0,0 +1,81 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ name: Lint & Type Check
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Set up Python
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.11"
20
+
21
+ - name: Install dev dependencies
22
+ run: pip install -e ".[dev]"
23
+
24
+ - name: Run ruff
25
+ run: ruff check src/ tests/ examples/ benchmarks/
26
+
27
+ - name: Run mypy
28
+ run: mypy src/agentflow/
29
+
30
+ test:
31
+ name: Tests (Python ${{ matrix.python-version }})
32
+ runs-on: ubuntu-latest
33
+ strategy:
34
+ fail-fast: false
35
+ matrix:
36
+ python-version: ["3.10", "3.11", "3.12"]
37
+
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+
41
+ - name: Set up Python ${{ matrix.python-version }}
42
+ uses: actions/setup-python@v5
43
+ with:
44
+ python-version: ${{ matrix.python-version }}
45
+
46
+ - name: Install dependencies
47
+ run: pip install -e ".[dev]"
48
+
49
+ - name: Run tests with coverage
50
+ run: pytest tests/ -v --cov=agentflow --cov-report=xml --cov-report=term-missing
51
+
52
+ - name: Upload coverage to Codecov
53
+ uses: codecov/codecov-action@v4
54
+ with:
55
+ file: ./coverage.xml
56
+ fail_ci_if_error: false
57
+ env:
58
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
59
+
60
+ build:
61
+ name: Build Distribution
62
+ runs-on: ubuntu-latest
63
+ needs: [lint, test]
64
+ steps:
65
+ - uses: actions/checkout@v4
66
+
67
+ - name: Set up Python
68
+ uses: actions/setup-python@v5
69
+ with:
70
+ python-version: "3.11"
71
+
72
+ - name: Install build tools
73
+ run: pip install build
74
+
75
+ - name: Build wheel and sdist
76
+ run: python -m build
77
+
78
+ - name: Check distributions
79
+ run: |
80
+ pip install twine
81
+ twine check dist/*
@@ -0,0 +1,32 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - "docs/**"
8
+ - "mkdocs.yml"
9
+ - "src/**"
10
+ - ".github/workflows/docs.yml"
11
+ workflow_dispatch:
12
+
13
+ permissions:
14
+ contents: write
15
+
16
+ jobs:
17
+ deploy:
18
+ name: Build & Deploy MkDocs
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Set up Python
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: "3.11"
27
+
28
+ - name: Install docs dependencies
29
+ run: pip install -e ".[docs]"
30
+
31
+ - name: Build and deploy to GitHub Pages
32
+ run: mkdocs gh-deploy --force
@@ -0,0 +1,33 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ publish:
10
+ name: Publish to PyPI
11
+ runs-on: ubuntu-latest
12
+ environment: release
13
+ permissions:
14
+ id-token: write # Required for OIDC trusted publishing
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: "3.11"
23
+
24
+ - name: Install build tools
25
+ run: pip install build
26
+
27
+ - name: Build distribution
28
+ run: python -m build
29
+
30
+ - name: Publish to PyPI
31
+ uses: pypa/gh-action-pypi-publish@release/v1
32
+ # No API key needed — uses OIDC trusted publishing
33
+ # Configure at: https://pypi.org/manage/project/agentflowkit/settings/publishing/
@@ -0,0 +1,21 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .venv/
8
+ venv/
9
+ .env
10
+ .pytest_cache/
11
+ *.egg
12
+ # AI assistants / agents
13
+ .claude/
14
+ CLAUDE.md
15
+ .cursor/
16
+ .cursorrules
17
+ .aider*
18
+ .github/copilot-instructions.md
19
+ AGENTS.md
20
+ chat.md
21
+ tmpclaude-*
@@ -0,0 +1,137 @@
1
+ # 🔍 Audit Report — `agentflowkit` v0.4.0
2
+
3
+ > **الوضع:** Pass 1 (تقرير فقط — ما تم تعديل أي سطر).
4
+ > **التاريخ:** 2026-07-03
5
+ > **الفرع:** `main` @ `03a370d`
6
+ > **المدقّق:** Claude (Opus 4.8) — Two-Pass Security & Health Audit
7
+
8
+ ---
9
+
10
+ ## 0. الملخّص التنفيذي
11
+
12
+ | البند | النتيجة |
13
+ |-------|---------|
14
+ | **Stack** | Python ≥3.10 · packaging: `hatchling` · quality: `ruff` + `mypy --strict` |
15
+ | **Core deps** | `openai>=1.0.0`, `pydantic>=2.0.0` (باقي backends: docker/redis/chromadb/aiomqtt = optional extras) |
16
+ | **Test baseline** | ✅ `202 passed, 11 skipped` بـ ~22s — كلها خضراء (التقرير الأصلي حكى 99؛ الواقع أكبر وأصحّ) |
17
+ | **Ruff (src)** | ❌ 2 errors بـ `swarm.py` |
18
+ | **Mypy (src)** | ❌ 1 error بـ `swarm.py` |
19
+ | **pip-audit** | ✅ ولا CVE بأي dependency حقيقي لـ agentflow |
20
+ | **Secrets / eval / exec** | ✅ نظيف |
21
+
22
+ **أهم 5 أولويات:**
23
+ 1. **D1** — تصليح lint/type بـ `swarm.py` (بوابة الجودة حمرا حالياً، إصلاح آمن 100%).
24
+ 2. **A1** — لفّ استدعاءات ChromaDB المتزامنة بـ `asyncio.to_thread` (blocking داخل الـ event loop).
25
+ 3. **S1** — قرار حول الـ sandbox fallback الصامت (يغيّر سلوك خارجي).
26
+ 4. **H1** — سقف عدد الجلسات بـ `InMemoryContext` (نمو ذاكرة غير محدود).
27
+ 5. **H2/A2/A3/H3/H4/H5** — تحصينات صغيرة آمنة.
28
+
29
+ **تنبيه على البيئة:** الـ `venv` المفحوص بيئة مشتركة (torch+cuda، transformers، streamlit، rembg، langchain…) مش معزولة لـ agentflow — بيأثّر على قراءة الـ CVEs (شوف القسم 3).
30
+
31
+ ---
32
+
33
+ ## 1. 🔒 Security & AI Risks (أولوية قصوى)
34
+
35
+ | # | Sev | Issue | File+Line | Impact | Suggested Fix |
36
+ |---|-----|-------|-----------|--------|---------------|
37
+ | S1 | 🟠 Med-High | **Fallback صامت لـ `SubprocessSandbox`** — لما Docker مش متوفر، `create_sandbox(prefer_docker=True)` بيرجع `SubprocessSandbox` اللي بشغّل كود الـ LLM مباشرة على الهوست (`sys.executable -c code`) بدون عزل. الاسم `sandboxed_tool` بيوحي بالأمان، والـ fallback بصير بصمت وقت الإعداد (في warning بس وقت التنفيذ). | `sandbox.py:389-415` | كود مولّد من LLM (يحتمل injection) ينفّذ على جهاز المستخدم بكامل صلاحياته. | opt-in صريح `allow_insecure_fallback=False`؛ إذا Docker مفقود وما في سماح → `raise`. **⚠️ يغيّر السلوك الخارجي — بدّه قرار.** |
38
+ | S2 | 🟡 Low | **Heredoc breakout بالـ C++** — الكود بينحطّ داخل `sh -c` heredoc بفاصل ثابت `AGENTFLOW_EOF`؛ كود فيه هاض السطر بيكسر الـ heredoc. | `sandbox.py:64-79` | منخفض: الكسر بيضل جوّا نفس الـ container المعزول (network none, cap_drop ALL, read_only). مش هروب من الحدود. | تمرير الكود عبر stdin أو file mount بدل heredoc. |
39
+ | S3 | 🟡 Low-Med | **Trust elevation بالـ prompt** — مخرجات الوكلاء/الأدوات السابقة بتنحقن بالـ **system** prompt (مقصوصة 300 حرف)؛ محتوى غير موثوق (نتيجة أداة web/MQTT) بيترفّع لمستوى system. | `agent.py:106-115` | منخفض-متوسط: بيضخّم prompt-injection؛ متأصّل بأطر الوكلاء. | نقل ذاكرة الجلسة لرسالة `user`/`assistant` مش `system`. informational. |
40
+ | S4 | 🟢 OK | **No hardcoded secrets / no eval / no exec** — بس placeholders بالـ tests/docs (`"test-key"`, `"sk-or-..."`). `subprocess` محصور بـ `sandbox.py` بالتصميم. | — | نظيف. | لا شيء. |
41
+ | S5 | 🟢 OK | **No path traversal بالـ loggers** — كتابة على stdout بس (`StreamHandler`)، ما في file paths. | `logging.py` | نظيف. | لا شيء. |
42
+
43
+ ---
44
+
45
+ ## 2. ⚙️ Async & Concurrency Health
46
+
47
+ | # | Sev | Issue | File+Line | Impact | Suggested Fix |
48
+ |---|-----|-------|-----------|--------|---------------|
49
+ | A1 | 🟠 Med | **استدعاءات ChromaDB متزامنة (blocking) جوّا `async def`** — كل دوال `VectorContext` معرّفة `async` بس بتنادي `._collection.upsert/.query/.get/.delete` المتزامنة مباشرة. مع `PersistentClient` (disk IO) أو حساب embeddings بيتجمّد الـ event loop. باقي الكود بيلفّ الـ blocking بـ `asyncio.to_thread` (DockerSandbox / tools.py) — هون غير متسق. | `memory.py:258-323` | تجميد الـ loop تحت الحمل. | `await asyncio.to_thread(self._collection.method, …)`. |
50
+ | A2 | 🟡 Low-Med | **RateLimiter ماسك الـ lock عبر `await sleep`** — `_wait_for_window` ماسك `self._lock` وهو نايم بالـ `asyncio.sleep`، فكل الكوروتينات الباقية بتتسكّر (تسلسل الإنتاجية)، والـ semaphore slot محجوز طول الانتظار. | `rate_limiter.py:47-59` | خنق الـ throughput، مش deadlock. | احسب مدة النوم تحت الـ lock، حرّر الـ lock، بعدها نام. |
51
+ | A3 | 🟡 Low | **تسرّب Semaphore عند الإلغاء** — `acquire()` بياخد الـ semaphore بعدها `_wait_for_window`؛ إلغاء أثناء النوم ما بيحرّر الـ slot. وبـ `llm.py` الـ `acquire()` برّا الـ try/finally (121 مقابل try 123). | `rate_limiter.py:36-39`, `llm.py:120-121` | حالة حافة ضيّقة (cancellation). | خلّي `acquire` يحرّر الـ semaphore إذا `_wait_for_window` رمى؛ أو انقل `acquire` جوّا try. |
52
+ | A4 | 🟢 OK | **`asyncio.gather`** — كلها `return_exceptions=True` مع معالجة، أو await متسلسل للـ tasks. ما في gather exceptions مهملة. | `pipeline.py:248,440,558`; `agent.py:283-286`; `swarm.py:162-163` | نظيف. | لا شيء. |
53
+ | A5 | 🟢 OK | **`InMemoryContext` locking** — قفل واحد متّسق، ما في await بين check/act يسبّب race، ولا nesting. | `memory.py:48-104` | نظيف. | لا شيء. |
54
+
55
+ ---
56
+
57
+ ## 3. 📦 Dependencies
58
+
59
+ ### النُّسخ (Installed vs Latest)
60
+
61
+ | Package | Installed | Latest | نوع | ملاحظة |
62
+ |---------|-----------|--------|-----|--------|
63
+ | `openai` | 1.99.9 | **2.44.0** | **MAJOR** | الكود بستورد `APIError, RateLimitError, AsyncOpenAI` + `openai.types.chat` — 2.x محتمل يكسر. **توصية بس.** |
64
+ | `pydantic-core` | 2.46.4 | 2.47.0 | minor | آمن (patch/minor). |
65
+ | `anyio` | 4.14.0 | 4.14.1 | patch | آمن. |
66
+ | `ruff` (dev) | 0.1.14 | 0.15.20 | — | ⚠️ مثبّت **أقل** من floor المعلن `>=0.4` بالـ pyproject. |
67
+ | `pytest-asyncio` (dev) | 0.23.3 | 1.4.0 | major | dev بس. |
68
+ | `pytest-cov` (dev) | 7.0.0 | 7.1.0 | minor | dev بس. |
69
+
70
+ ### CVEs (pip-audit)
71
+
72
+ ✅ **ولا CVE بأي من dependencies الحقيقية لـ agentflow** (`openai`, `pydantic`).
73
+
74
+ كل الثغرات المكتشفة بحزم **مش تابعة** لـ agentflow، موجودة بالـ venv المشترك:
75
+
76
+ ```
77
+ setuptools 65.5.0 CVE-2024-6345 (RCE), PYSEC-2025-49 (path traversal), PYSEC-2022-43012
78
+ starlette 0.37.2 عدة CVEs (2024-2026)
79
+ tornado 6.5.2 عدة CVEs (2026)
80
+ werkzeug 3.1.3 CVE-2025-66221, CVE-2026-21860, CVE-2026-27199
81
+ transformers 4.57.6 PYSEC-2025-217, CVE-2026-1839, CVE-2026-4372
82
+ streamlit 1.53.1 CVE-2026-33682
83
+ pyarrow / rembg / wheel ثغرات إضافية
84
+ ```
85
+
86
+ - كل هدول **مش** dependencies لـ agentflow.
87
+ - تنبيه: الـ extra الاختياري `chromadb` بيجرّ transitively `fastapi/starlette/uvicorn`.
88
+ - **توصية:** شغّل الـ audit بـ venv معزول فيه agentflow + extras بس عشان قراءة دقيقة.
89
+
90
+ ---
91
+
92
+ ## 4. 🔁 Duplicated Logic & Refactors
93
+
94
+ | # | Sev | Issue | File+Line | Impact | Suggested Fix |
95
+ |---|-----|-------|-----------|--------|---------------|
96
+ | D1 | 🟠 Med | **Lint/type فاشلة بـ `swarm.py`** — `ruff`: B007 (`iteration` unused @104)، F841 (`arguments` unused @148). `mypy`: no-untyped-def @184 (`_make_delegate_fn`). بوابة الجودة **حالياً حمرا**. | `swarm.py:104,148,184` | إصلاحات تافهة وآمنة. | `for _ in range(...)`، احذف `arguments` المكرّر، ضيف return type annotation. **✅ أسهل مكسب.** |
97
+ | D2 | 🟠 Med | **بلوك HITL pause/persist مكرّر 3×** حرفياً. | `pipeline.py:250-296, 442-485, 560-595` | صيانة مؤلمة. | استخرج helper `_persist_pause_state(...)`. **⚠️ يلمس تدفق pipeline — بدّه قرار.** |
98
+ | D3 | 🟡 Low | **حلقة ReAct مكرّرة** بين الوكيل والـ supervisor. | `agent.py:195-307` vs `swarm.py:104-182` | تكرار كبير بس **core logic**. | **توصية بس — ممنوع لمسها حسب القيود.** |
99
+ | D4 | 🟡 Low | **guard استيراد redis مكرّر** بنمطين مختلفين. | `cache.py:80-84` vs `memory.py:108-135` | بسيط. | توحيد النمط. |
100
+
101
+ ---
102
+
103
+ ## 5. 🩺 General Health
104
+
105
+ | # | Sev | Issue | File+Line | Impact | Suggested Fix |
106
+ |---|-----|-------|-----------|--------|---------------|
107
+ | H1 | 🟠 Med | **نمو `InMemoryContext` غير محدود بالجلسات** — `max_entries` بحدّ الإدخالات **لكل جلسة**، بس عدد الجلسات (`self._store` keys) غير محدود. الجلسات المنتهية بتتنظّف بس لما تتقرا هي بالذات عبر `load_context`. workload بيولّد session_id فريد لكل طلب وما بيرجع يقراه = تسرّب ذاكرة. | `memory.py:60, 78-91` | نمو ذاكرة غير محدود. | سقف max-sessions/sweep دوري، أو توثيق إن الـ caller لازم `clear()`. |
108
+ | H2 | 🟡 Low | **`getattr` برّا الـ try بـ tools** — `kwargs = {k: getattr(validated, k) for k in arguments}` قبل الـ try؛ إذا الـ LLM بعت مفتاح زيادة (pydantic بتجاهله)، `getattr` بترمي `AttributeError` غير ملفوفة بـ `ToolError`. | `tools.py:94` | منخفض. | كرّر على حقول الموديل مش مفاتيح `arguments`، أو انقل جوّا try. |
109
+ | H3 | 🟡 Low | **ما في لفّ لأخطاء Redis** — استثناءات redis الخام بتنتشر بدل framework error (غير متّسق مع لفّ `LLMError`/`ToolError`). | `memory.py:186-201`, `cache.py:119-131` | منخفض. | لفّ استدعاءات redis. |
110
+ | H4 | 🟡 Low | **`InMemoryCache` موصوف "Thread-safe" بدون قفل** — dict عادي بلا lock (بعكس `InMemoryContext`). آمن ضمن الـ event loop بس، مش thread-safe فعلياً؛ وكمان FIFO مش LRU رغم التسمية. | `cache.py:36-70` | docstring مضلّل. | صحّح الـ docstring أو ضيف قفل. |
111
+ | H5 | 🟡 Low | **DockerSandbox `read_only=True` مع كتابة `/tmp`** — مسار الـ C++ بيكتب `/tmp/code.cpp` بس الـ container read-only بلا tmpfs → تنفيذ C++ بالـ Docker بيفشل runtime. | `sandbox.py:201, 73-76` | خلل وظيفي (مش أمني). | ضيف `tmpfs={"/tmp": ""}` أو `read_only=False`. |
112
+
113
+ ---
114
+
115
+ ## 6. القرارات المعلّقة (بدّها موافقتك)
116
+
117
+ | القرار | الوصف | الخيار |
118
+ |--------|-------|--------|
119
+ | **S1** | الـ sandbox fallback الصامت | نضيف `allow_insecure_fallback` ونمنع الـ fallback الصامت؟ (يغيّر سلوك) |
120
+ | **D2** | HITL persist helper | نستخرج helper (يلمس pipeline flow)؟ |
121
+ | **D3** | ReAct dedup | توصية فقط — ممنوع اللمس حسب القيود |
122
+ | **openai 2.x** | ترقية major | نتركها توصية أم نجرّبها بفرع منفصل؟ |
123
+
124
+ ---
125
+
126
+ ## 7. خطة Pass 2 المقترحة (بعد الموافقة)
127
+
128
+ **المجموعة الآمنة (ما بتغيّر سلوك — بتنفّذ مباشرة بعد الموافقة):**
129
+ `D1` (lint/type) → `A1` (to_thread) → `H1` (session cap) → `H2` (try scope) → `A2`+`A3` (rate limiter) → `H3` (redis wrap) → `H4` (docstring) → `H5` (tmpfs) → dependency patches (anyio, pydantic-core).
130
+
131
+ **بعد كل مجموعة:** `pytest` + `ruff` + `mypy` — والـ 202 لازم تضل خضرا.
132
+
133
+ **تُترك كتوصيات فقط:** `S1`, `D2`, `D3`, `openai 2.x`.
134
+
135
+ ---
136
+
137
+ *انتهى Pass 1 — ما تم تعديل أي سطر بالكود.*
@@ -0,0 +1,111 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented here.
4
+
5
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ---
9
+
10
+ ## [0.3.0]
11
+
12
+ ### Added
13
+ - **Tool / function calling** (`tools.py`): the `@tool` decorator turns any sync
14
+ or async Python function into an LLM-callable tool. Argument JSON schemas are
15
+ generated automatically from type hints via Pydantic. Agents given `tools=[...]`
16
+ run a bounded **ReAct loop** (call → execute tools → observe → repeat) up to
17
+ `max_tool_iterations` (default 6). Tool errors are fed back to the model for
18
+ recovery. New `ToolError` exception; tool-call traces recorded in
19
+ `AgentResult.metadata["tool_calls"]`.
20
+ - **Cost tracking** (`pricing.py`): built-in USD price tables for common OpenAI
21
+ and Anthropic models with longest-prefix matching. `LLM.generate()` returns a
22
+ `cost` (and `prompt_tokens`/`completion_tokens`); `AgentResult.cost` and
23
+ `PipelineResult.total_cost` aggregate spend. Cache hits bill `0.0`.
24
+ `register_price()` / `estimate_cost()` are public.
25
+ - **Token streaming**: `LLM.astream()` yields content deltas token-by-token for
26
+ interactive UIs (honours the rate limiter; no cache/retry mid-stream).
27
+ - **Observability hooks** (`observability.py`): `Hooks` base class + `LoggingHooks`
28
+ wire the previously-unused `PipelineLogger` into `Pipeline.run()` (which was
29
+ silent before). A raising hook is caught and warned, never crashing the run.
30
+ - **Production-grade retry**: unified exponential backoff with jitter and
31
+ `Retry-After` header support. New `LLM(retry_base_delay=, retry_jitter=)` args.
32
+ - **Documentation site**: MkDocs Material + mkdocstrings under `docs/`, deployed
33
+ via a new `docs.yml` workflow. New `docs` optional-dependency group.
34
+ - New examples: `tool_agent.py`, `streaming_and_cost.py`; and
35
+ `benchmarks/parallel_speedup.py`.
36
+
37
+ ### Fixed
38
+ - **`py.typed` marker** added — the package advertised `Typing :: Typed` but
39
+ shipped no marker, so downstream type-checkers saw no types.
40
+ - **Red CI made green**: resolved 1 `ruff` error (B904) and 7 `mypy --strict`
41
+ errors across `llm.py`, `cache.py`, `logging.py`, `events.py`, `pipeline.py`.
42
+
43
+ ### Changed
44
+ - `__version__` bumped to `0.3.0`.
45
+ - Test coverage raised to ~91%; `fail_under` tightened from 80 → 90.
46
+ - `Pipeline.__init__` gains a `hooks` parameter; `run()` now emits lifecycle
47
+ events and generates `run_id` up front.
48
+
49
+ ---
50
+
51
+ ## [0.2.0]
52
+
53
+ ### Added
54
+ - **Parallel execution**: Agents at the same DAG level now run concurrently via
55
+ `asyncio.gather()`. `_resolve_levels()` replaces `_resolve_order()` and uses
56
+ Kahn's algorithm to group independent agents.
57
+ - **Per-agent timeout**: `Pipeline.add(timeout=N)` wraps each agent coroutine with
58
+ `asyncio.wait_for`; raises `AgentTimeoutError` on expiry.
59
+ - **Conditional branching**: `Pipeline.add(condition=lambda ctx: ...)` allows
60
+ dynamic skipping of agents based on upstream outputs. Skipped agents emit
61
+ `agent_skipped` events in streaming mode.
62
+ - **Pipeline-level retry**: `Pipeline(retry_failed_agents=N)` retries failed
63
+ agents up to N times with exponential backoff (1s, 2s, 4s). Timeouts are
64
+ non-retriable.
65
+ - **LLM response caching** (`cache.py`): `ResponseCache` ABC with `InMemoryCache`
66
+ (SHA-256 key, lazy TTL eviction, max-size LRU) and `RedisCache` (optional dep).
67
+ Cache is wired into `LLM(cache=...)`.
68
+ - **Rate limiting** (`rate_limiter.py`): `RateLimiter(requests_per_minute, max_concurrent)`
69
+ using `asyncio.Semaphore` + sliding-window counter. Async context manager interface.
70
+ Wired into `LLM(rate_limiter=...)`.
71
+ - **Structured logging** (`logging.py`): `PipelineLogger` (LoggerAdapter with JSON
72
+ formatter) carrying `run_id` and `pipeline` through all log records.
73
+ - **Agent output validation**: `@Agent(output_schema=MyPydanticModel)` validates
74
+ LLM response JSON against a Pydantic v2 model; raises `AgentOutputValidationError`
75
+ on failure.
76
+ - New exception classes: `AgentTimeoutError`, `AgentOutputValidationError`.
77
+ - `AgentResult` gains: `cached`, `level`, `timestamp` fields.
78
+ - `PipelineResult` gains: `run_id`, `levels_executed`, `agents_with_cache_hits` fields.
79
+ - `Event.type` now documents all valid values including `"agent_skipped"`.
80
+ - GitHub Actions CI workflow (lint, test matrix py3.10-3.12, codecov, build check).
81
+ - GitHub Actions publish workflow (OIDC trusted publishing on version tags).
82
+ - Issue templates for bug reports and feature requests.
83
+ - `CONTRIBUTING.md` with development setup and PR checklist.
84
+ - `pythonpath = ["src"]` in pytest config to fix editable install on non-ASCII paths.
85
+
86
+ ### Changed
87
+ - `__version__` bumped to `0.2.0`.
88
+ - `pipeline.py`: `Pipeline.__init__` gains `retry_failed_agents` parameter.
89
+ - `pipeline.py`: `Pipeline.add` gains `timeout` and `condition` parameters.
90
+ - `llm.py`: `LLM.__init__` gains `cache` and `rate_limiter` parameters.
91
+ Return dict from `generate()` now includes `"cached"` key.
92
+ - `pyproject.toml`: classifier updated to Beta; dev extras expanded;
93
+ `ruff`, `mypy`, `coverage` tool config sections added.
94
+
95
+ ### Performance
96
+ - Two independent agents that each take 0.1s now complete in ~0.1s (parallel),
97
+ not ~0.2s (sequential).
98
+
99
+ ---
100
+
101
+ ## [0.1.0] — 2026-02-27
102
+
103
+ ### Added
104
+ - Initial release.
105
+ - `@Agent` decorator and `BaseAgent` ABC for defining agents.
106
+ - `Pipeline` with topological sort (`_resolve_order`) for dependency resolution.
107
+ - `LLM` provider abstraction with OpenAI-compatible API, retry logic.
108
+ - `EventEmitter` + `pipeline.stream()` for async event streaming.
109
+ - Pydantic v2 data models: `AgentResult`, `PipelineResult`, `Event`.
110
+ - Custom exception hierarchy: `AgentFlowError`, `AgentError`, `LLMError`, `PipelineError`.
111
+ - Published to PyPI as `agentflowkit`.
@@ -0,0 +1,30 @@
1
+ cmake_minimum_required(VERSION 3.15)
2
+ project(agentflow_cpp LANGUAGES NONE)
3
+
4
+ set(SKIP_CPP_EXTENSION OFF CACHE BOOL "Skip building the C++ pybind11 extension")
5
+
6
+ if(NOT SKIP_CPP_EXTENSION)
7
+ include(CheckLanguage)
8
+ check_language(CXX)
9
+ if(CMAKE_CXX_COMPILER)
10
+ enable_language(CXX)
11
+ set(CMAKE_CXX_STANDARD 17)
12
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
13
+ endif()
14
+ endif()
15
+
16
+ if(CMAKE_CXX_COMPILER AND NOT SKIP_CPP_EXTENSION)
17
+ find_package(pybind11 CONFIG QUIET)
18
+ if(pybind11_FOUND)
19
+ message(STATUS "pybind11 found — building _agentflow_cpp extension")
20
+ pybind11_add_module(_agentflow_cpp
21
+ src/agentflow/cpp_core/bindings.cpp
22
+ src/agentflow/cpp_core/dag_engine.cpp
23
+ )
24
+ target_include_directories(_agentflow_cpp PRIVATE src/agentflow/cpp_core)
25
+ else()
26
+ message(STATUS "pybind11 not found — skipping _agentflow_cpp extension (Python fallback will be used)")
27
+ endif()
28
+ else()
29
+ message(STATUS "C++ compiler not available — skipping _agentflow_cpp extension (Python fallback will be used)")
30
+ endif()
@@ -0,0 +1,99 @@
1
+ # Contributing to agentflowkit
2
+
3
+ Thank you for your interest in contributing! This guide explains how to work on the project.
4
+
5
+ ## Development Setup
6
+
7
+ ```bash
8
+ git clone https://github.com/KaramQ6/agentflow.git
9
+ cd agentflow
10
+ pip install -e ".[dev]"
11
+ ```
12
+
13
+ Verify your setup:
14
+
15
+ ```bash
16
+ pytest tests/ -v
17
+ ```
18
+
19
+ All tests should pass before you start making changes.
20
+
21
+ ## Project Structure
22
+
23
+ ```
24
+ src/agentflow/
25
+ ├── agent.py # @Agent decorator + BaseAgent ABC
26
+ ├── cache.py # ResponseCache, InMemoryCache, RedisCache
27
+ ├── events.py # EventEmitter for streaming
28
+ ├── exceptions.py # Exception hierarchy
29
+ ├── llm.py # LLM provider abstraction
30
+ ├── logging.py # PipelineLogger (structured JSON)
31
+ ├── pipeline.py # Pipeline DAG orchestration (core)
32
+ ├── rate_limiter.py # RateLimiter (RPM + concurrency)
33
+ └── types.py # Pydantic data models
34
+ ```
35
+
36
+ ## Code Style
37
+
38
+ We use **ruff** for linting + formatting and **mypy** for type checking.
39
+
40
+ ```bash
41
+ ruff check src/ tests/ # Lint
42
+ ruff format src/ tests/ # Format
43
+ mypy src/agentflow/ # Type check
44
+ ```
45
+
46
+ All code must:
47
+ - Have full type hints
48
+ - Pass `ruff check` with no errors
49
+ - Pass `mypy` in strict mode
50
+
51
+ ## Adding a Feature
52
+
53
+ ### New cache backend
54
+
55
+ 1. Subclass `ResponseCache` in `cache.py`
56
+ 2. Implement `async get(key)` and `async set(key, value, ttl)`
57
+ 3. Add to `__all__` in `__init__.py`
58
+ 4. Write tests in `tests/test_cache.py`
59
+
60
+ ### New exception type
61
+
62
+ 1. Add to `exceptions.py` (subclass the appropriate parent)
63
+ 2. Add to `__all__` in `__init__.py`
64
+ 3. Import and use in the relevant module
65
+
66
+ ### New pipeline feature
67
+
68
+ 1. Add to `pipeline.py` — keep changes localized to `_PipelineNode`, `Pipeline.add()`, or the execution loop
69
+ 2. Emit appropriate events for streaming consumers
70
+ 3. Write tests in `tests/test_parallel.py` or a new test file
71
+
72
+ ## Pull Request Checklist
73
+
74
+ - [ ] Tests added for new functionality
75
+ - [ ] All existing tests still pass (`pytest tests/ -v`)
76
+ - [ ] Type hints on all new functions and classes
77
+ - [ ] Docstrings on public API additions
78
+ - [ ] Entry added to `[Unreleased]` section in `CHANGELOG.md`
79
+ - [ ] No new dependencies added without discussion in an issue first
80
+
81
+ ## Commit Message Convention
82
+
83
+ We use [Conventional Commits](https://www.conventionalcommits.org/):
84
+
85
+ ```
86
+ feat: add Redis cache backend
87
+ fix: handle asyncio.TimeoutError in _execute_node
88
+ docs: add caching section to README
89
+ test: add parallel execution timing test
90
+ refactor: extract _resolve_levels from _resolve_order
91
+ ```
92
+
93
+ ## Running the Full Suite
94
+
95
+ ```bash
96
+ pytest tests/ -v --cov=agentflow --cov-report=term-missing
97
+ ```
98
+
99
+ Coverage should remain ≥ 80%.